5 Maneiras pelas Quais o Desenvolvimento de Aplicações Ergo Mudou Para Sempre Graças ao Appkit
3 de dezembro de 2019

Agradecimentos a Robert Kornacki e Denys Zadorozhnyi.
Ergo Appkit é uma biblioteca para
desenvolvimento poliglota de Aplicações Ergo baseada em
GraalVM. GraalVM tem muitos ótimos
casos de uso. Expandindo isso, neste artigo vamos passar por algumas das funcionalidades do Appkit
herdadas do GraalVM e levá-lo passo a passo para aprender como tirar proveito delas.
- 0. Cenário de Exemplo
- 1. Desenvolvimento de Aplicações Java Ergo
- 2. Aplicações Ergo de Baixo Consumo e Rápido Início
- 3. Desenvolver Aplicações Ergo em JavaScript, Python, Ruby
- 4. Bibliotecas Compartilhadas Nativas do Ergo
- 5. Depurar Sua Aplicação Ergo Poliglota
Cenário de Exemplo
Vamos criar uma simples aplicação de console (chamada
FreezeCoin)
em Java que usa a biblioteca Appkit. Usando o Appkit, seremos capazes de enviar facilmente uma nova transação para um nó Ergo programaticamente. A
transação transferirá uma determinada quantidade de Erg para uma nova caixa protegida pelo
seguinte contrato Ergo escrito em ErgoScript (veja esta
introdução e mais exemplos
avançados para aprender mais sobre ErgoScript).
// Contrato Freezer
{
// Parâmetros
// freezeDeadline: Int - algum número de bloco futuro após o qual a caixa pode ser gasta
// ownerPk: SigmaProp - chave pública do novo proprietário da caixa
sigmaProp(HEIGHT > freezeDeadline) && ownerPk
}
Em resumo, uma caixa (e, portanto, os fundos dentro da caixa) estão bloqueados sob um contrato (ou script) na blockchain Ergo. Para que a caixa seja gasta, o contrato deve avaliar como verdadeiro. Assim, a pessoa que deseja gastar a caixa deve garantir que o contrato avalie como verdadeiro com base na lógica codificada dentro dele.
Nosso contrato Freezer acima verifica as seguintes condições antes de permitir que a caixa seja gasta:
-
O número do bloco atual da blockchain Ergo (também conhecido como ALTURA da blockchain) é
maior que o prazo especificado -
A transação de gasto deve ser assinada pelo proprietário da chave secreta
correspondente à chave pública ownerPk.
A primeira condição proíbe qualquer um de gastar a caixa antes que a blockchain Ergo
cresça até a altura dada. Como novos blocos na blockchain são minerados aproximadamente a cada 2 minutos em média, usando a altura
atual da blockchain é fácil definir qualquer duração de atraso que desejamos, como 1 dia, 1 semana ou 1 mês. (ou seja, (60 / 2) * 24 * 7 = 5040, que é o número de blocos por semana).
Agora vamos nos aprofundar em como podemos pegar este Contrato Freezer e integrá-lo com a biblioteca Apkit para criar a aplicação de console FreezeCoin, para que qualquer um possa escolher congelar suas moedas se assim desejar. (Concedido, este contrato/dApp não é realmente útil, no entanto, é um exemplo simples eficaz para mostrar como esta pilha de tecnologia funciona para que você mesmo possa construir dApps úteis no futuro.)
1. Desenvolvimento de Aplicações Java Ergo
O Appkit visa fornecer um conjunto de interfaces que podem ser usadas idiomaticamente
em Java. Você se sentirá em casa usando o Appkit se for um veterano em Java.
Por favor, siga as instruções de configuração para GraalVM e
Appkit se desejar reproduzir os exemplos abaixo.
Para usar o Appkit em nossa implementação Java do FreezeCoin, devemos adicionar a
dependência a seguir no arquivo gradle
dependencies {
implementation("org.ergoplatform", "ergo-appkit_2.12", "3.1.0", "compile")
...
}
Além disso, em tempo de execução, o Appkit/nossa aplicação precisa se conectar a um Nó Ergo via API REST. Frequentemente,
o nó estará rodando localmente e disponível em http://localhost:9052/. Este é o cenário padrão para qualquer um que tenha configurado um nó completo seguindo estas
instruções e está usando a configuração padrão.
A partir de agora, assumiremos que você configurou e iniciou seu Nó Ergo para que ele esteja disponível para teste da aplicação.
Em seguida, nossa aplicação precisará saber como se conectar ao nosso nó local em execução, além de outras várias configurações para funcionar corretamente. Usaremos um arquivo json com os seguintes
parâmetros de configuração que nosso aplicativo FreezeCoin carregará na inicialização.
{
"node": {
"nodeApi": {
"apiUrl": "http://localhost:9052/",
"apiKey": "coloque sua chave api secreta gerada durante a configuração do nó aqui"
},
"wallet": {
"mnemonic": "a chave mnemônica usada para inicializar ou restaurar a carteira do nó",
"password": "a senha que você escolheu para proteger a carteira",
"mnemonicPassword": "a senha que você escolheu para proteger a mnemônica"
},
"networkType": "TESTNET"
},
"parameters": {
"newBoxSpendingDelay": "30",
"ownerAddress": "3WzR39tWQ5cxxWWX6ys7wNdJKLijPeyaKgx72uqg9FJRBCdZPovL"
}
}
Aqui apiKey é a chave secreta necessária para autenticação da API que pode ser
adquirida conforme descrito
aqui.
Sua mnemônica é a frase secreta obtida durante a configuração de uma nova
carteira.
Como nosso aplicativo funcionará é que o usuário o lançará a partir da linha de comando e fornecerá um argumento. Este argumento é a quantidade de valor (em NanoErgs) que eles desejam congelar/bloquear sob o contrato Freezer que escrevemos acima.
Nosso primeiro passo para nosso aplicativo FreezeCoin será ler o arquivo de configuração json que acabamos de criar e aceitar o argumento da linha de comando do usuário:
public static void main(String[] args) {
long amountToSend = Long.parseLong(args[0]); // valor positivo em NanoErg
ErgoToolConfig conf = ErgoToolConfig.load("freeze_coin_config.json");
// o restante do código discutido abaixo
...
}
Com isso adquirido, agora podemos obter o atraso de gasto e o endereço do proprietário que foram definidos no arquivo de configuração json.
int newBoxSpendingDelay = Integer.parseInt(conf.getParameters().get("newBoxSpendingDelay"));
Address ownerAddress = Address.create(conf.getParameters().get("ownerAddress"));
Em seguida, precisamos nos conectar ao nó Ergo em execução a partir de nossa aplicação Java para que possamos usar os dados que acabamos de analisar e postar algo na blockchain. Isso é feito criando
uma instância de ErgoClient que usa nossos valores pré-definidos para nosso nó a partir do arquivo de configuração json também.
ErgoNodeConfig nodeConf = conf.getNode();
ErgoClient ergoClient = RestApiErgoClient.create(nodeConf);
Agora que temos uma instância de ErgoClient,
podemos executar qualquer bloco de código e ter acesso ao contexto atual da blockchain.
String txJson = ergoClient.execute((BlockchainContext ctx) -> {
// use ctx aqui para criar e assinar uma nova transação
// então envie para o nó
});
A lambda passada para execute é chamada quando o contexto atual da blockchain
é carregado do nó Ergo. Nesta lambda nós
colocaremos nossa lógica de aplicação.
Primeiro começamos com alguns passos auxiliares.
// acessar a carteira embutida no nó Ergo
// (usando a carteira especificada via mnemônica que colocamos em freeze_coin_config.json)
ErgoWallet wallet = ctx.getWallet();
// calcular a quantidade total de NanoErgs que precisamos enviar para a nova caixa
// incluindo o pagamento das taxas de transação
long totalToSpend = amountToSend + Parameters.MinFee;
// solicitar caixas não gastas que cubram a quantidade necessária de NanoErgs da carteira
Optional<List<InputBox>> boxes = wallet.getUnspentBoxes(totalToSpend);
if (!boxes.isPresent())
throw new ErgoClientException(
"Não há moedas suficientes em sua carteira especificada para pagar " + totalToSpend, null);
// criar um "prover", que é um objeto especial que será usado para assinar a transação
// o prover deve ser configurado com os segredos da sua carteira, que são necessários para gerar assinaturas (ou seja, provas)
ErgoProver prover = ctx.newProverBuilder()
.withMnemonic(
nodeConf.getWallet().getMnemonic(),
nodeConf.getWallet().getPassword())
.build();
Neste ponto, temos as caixas de entrada escolhidas para nossa transação de gasto, mas agora precisamos criar uma caixa de saída com a amountToSend especificada e bloqueada sob o contrato Freezer.
// a única maneira de criar uma transação é usando o construtor tx obtido do contexto
// o construtor usa o contexto para acessar os dados necessários da blockchain.
UnsignedTransactionBuilder txB = ctx.newTxBuilder();
// criar nova caixa usando novo construtor obtido do construtor de transação
// neste caso, compilamos um novo ErgoContract a partir do código ErgoScript do Freezer
OutBox newBox = txB.outBoxBuilder()
.value(amountToPay)
.contract(ctx.compileContract(
ConstantsBuilder.create()
.item("freezeDeadline", ctx.getHeight() + newBoxSpendingDelay)
.item("ownerPk", ownerAddress.getPublicKey())
.build(),
"{ sigmaProp(HEIGHT > freezeDeadline) && ownerPk }"))
.build();
Observe que, para compilar ErgoContract a partir do código fonte do script Freezer, o método compileContract
exige que forneçamos valores para constantes nomeadas que são usadas dentro do script.
Se nenhuma dessas constantes for usada, então ConstantsBuilder.empty() pode ser passado para ele.
Neste caso, passamos a chave pública do novo proprietário da caixa para o ownerPk
placeholder no script. Para repetir o que foi dito anteriormente, isso significa que a caixa só pode ser gasta pelo proprietário da
chave secreta correspondente.
Em seguida, criamos uma transação não assinada usando todos os dados que reunimos até agora.
// fornecer ao construtor da transação quais caixas vamos gastar, quais saídas
// devem ser criadas, as taxas totais da transação e o endereço para onde a mudança deve ser enviada
UnsignedTransaction tx = txB.boxesToSpend(boxes.get())
.outputs(newBox)
.fee(Parameters.MinFee)
.sendChangeTo(prover.getP2PKAddress())
.build();
E finalmente nós:
- Usamos o prover para assinar a transação construída
- Assim obtemos uma instância de
SignedTransaction - Usamos o contexto da blockchain para enviar a transação assinada para
o nó Ergo.
O txId resultante pode ser usado para se referir a esta transação
mais tarde, no entanto, não o usamos aqui.
SignedTransaction signed = prover.sign(tx);
String txId = ctx.sendTransaction(signed);
return signed.toJson(true);
Como você pode ter notado, para nosso passo final, mostramos que é possível serializar a transação assinada em uma string Json com a impressão bonita ativada. Veja o código fonte completo
do exemplo para mais detalhes e para usá-lo como um modelo em sua própria
aplicação.
Agora com todo o código definido, podemos executar nossa aplicação FreezeCoin usando os seguintes passos
(assumindo que você está no diretório onde clonou
ergo-appkit-examples).
$ pwd
o/diretório/que/você/clonou/ergo-appkit-examples
$ ./gradlew clean shadowJar
Este comando irá montar o arquivo build/libs/appkit-examples-3.1.0-all.jar contendo
nossa aplicação Java FreezeCoin e todas as suas dependências em um único jar grande.
Observe que este passo deve ser repetido após quaisquer alterações feitas no código fonte Java de nossa aplicação.
Tendo criado nossa aplicação, agora podemos usar nosso aplicativo FreezeCoin:
$ java -cp build/libs/appkit-examples-3.1.0-all.jar \
org.ergoplatform.appkit.examples.FreezeCoin 1000000000
Você receberá algo semelhante a esta saída no console.
E com isso sua transação foi aceita pelo nó Ergo e transmitida para a rede onde aguardará no pool de transações para ser adicionada a um bloco. Uma vez que um minerador a selecione e a adicione a um bloco, suas moedas estarão oficialmente "congeladas" dentro da nova caixa com base nos valores que você forneceu à aplicação FreezeCoin.
O exemplo assume que o nó Ergo (e a carteira embutida) é de propriedade do
usuário do FreezeCoin. No entanto, isso não é estritamente necessário e as interfaces do Appkit
podem ser usadas para criar e enviar novas transações usando nós públicos Ergo arbitrários.
2. Aplicações Ergo de Baixo Consumo e Rápido Início
Como você pode saber, usar Java para processos de curta duração tem muitas desvantagens.
As aplicações tendem a sofrer com longos tempos de inicialização e uso de memória relativamente alto.
Vamos executar o FreezeCoin usando o comando de tempo para
obter o tempo real (tempo decorrido em relógio) que leva para o programa inteiro rodar do
início ao fim. Usamos a flag -l para imprimir o uso de memória também.
$ /usr/bin/time -l java -cp build/libs/appkit-examples-3.1.0-all.jar \
org.ergoplatform.appkit.examples.FreezeCoin 1000000000
...
4.97 real 8.41 user 0.69 sys
513703936 tamanho máximo do conjunto residente
0 tamanho médio da memória compartilhada
0 tamanho médio de dados não compartilhados
0 tamanho médio da pilha não compartilhada
125010 reaquisições de página
1216 falhas de página
0 trocas
0 operações de entrada de bloco
0 operações de saída de bloco
13 mensagens enviadas
86 mensagens recebidas
1 sinais recebidos
2384 trocas de contexto voluntárias
17409 trocas de contexto involuntárias
Como visto acima, esta pequena aplicação levou 2 threads paralelas quase 4
segundos para rodar. A maior parte desse tempo pode ser atribuída à inicialização da JVM e
a execução do compilador JIT em segundo plano. Este é um desempenho bastante abaixo do esperado, e sabemos que podemos fazer muito melhor.
Felizmente, o GraalVM nos fornece a solução perfeita.
Podemos resolver esse problema inerente à JVM compilando o código Java
ahead-of-time em uma imagem executável nativa via GraalVM. Isso evita a necessidade de usar o compilador just-in-time do Java
em tempo de execução.
A experiência para nós (o desenvolvedor usando GraalVM) é bastante semelhante a um compilador convencional como o gcc. Observe,
que pode ser necessário executar ./gradlew clean shadowJar primeiro.
$ ./gradlew clean shadowJar
$ native-image --no-server \
-cp build/libs/appkit-examples-3.1.0-all.jar\
--report-unsupported-elements-at-runtime\
--no-fallback -H:+TraceClassInitialization -H:+ReportExceptionStackTraces\
-H:+AddAllCharsets -H:+AllowVMInspection -H:-RuntimeAssertions\
--allow-incomplete-classpath \
--enable-url-protocols=http,https org.ergoplatform.appkit.examples.FreezeCoin freezecoin
[freezecoin:3133] classlist: 35,217.78 ms
[freezecoin:3133] (cap): 6,063.07 ms
[freezecoin:3133] setup: 8,268.99 ms
[freezecoin:3133] (typeflow): 60,238.25 ms
[freezecoin:3133] (objects): 33,009.06 ms
[freezecoin:3133] (features): 4,796.86 ms
[freezecoin:3133] analysis: 102,876.01 ms
[freezecoin:3133] (clinit): 11,642.43 ms
[freezecoin:3133] universe: 13,718.96 ms
[freezecoin:3133] (parse): 5,053.18 ms
[freezecoin:3133] (inline): 18,317.24 ms
[freezecoin:3133] (compile): 44,806.82 ms
[freezecoin:3133] compile: 72,288.24 ms
[freezecoin:3133] image: 7,955.29 ms
[freezecoin:3133] write: 2,872.25 ms
[freezecoin:3133] [total]: 243,813.30 ms
O simples comando acima produz um executável nativo completo chamado freezecoin.
Para enfatizar, este executável não é apenas um lançador para a JVM. Na verdade, ele não se vincula à JVM ou agrupa
a JVM de qualquer forma. native-image compila o código do FreezeCoin, bem como quaisquer
bibliotecas Java das quais depende, tudo até código de máquina simples.
Se olharmos para as bibliotecas que freezecoin usa, você pode ver que ele usa apenas bibliotecas de sistema padrão. Assim, podemos mover apenas este único executável para outro sistema
que não tenha uma JVM instalada e ele funcionará lá sem problemas.
$ otool -L freezecoin # ldd freezecoin no Linux
freezecoin:
/usr/lib/libSystem.B.dylib (versão de compatibilidade 1.0.0, versão atual 1252.50.4)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (versão de compatibilidade 150.0.0, versão atual 1455.12.0)
/usr/lib/libz.1.dylib (versão de compatibilidade 1.0.0, versão atual 1.2.11)
Se temporizarmos este novo executável freezecoin, podemos ver que ele inicia aproximadamente 8x mais rápido e usa
cerca de 6x menos memória. O que isso significa é que você não sente aquela pausa palpável que sempre ocorre ao executar um
programa de curta duração com a JVM.
$ DYLD_LIBRARY_PATH=$GRAAL_HOME/jre/lib /usr/bin/time -l ./freezecoin 1800000000
0.43 real 0.15 user 0.03 sys
81289216 tamanho máximo do conjunto residente
0 tamanho médio da memória compartilhada
0 tamanho médio de dados não compartilhados
0 tamanho médio da pilha não compartilhada
20079 reaquisições de página
0 falhas de página
0 trocas
0 operações de entrada de bloco
0 operações de saída de bloco
13 mensagens enviadas
86 mensagens recebidas
0 sinais recebidos
11 trocas de contexto voluntárias
138 trocas de contexto involuntárias
Este é apenas um dos grandes benefícios do GraalVM que podemos aproveitar com o Appkit.
3. Desenvolver Aplicações Ergo em JavaScript, Python, Ruby
O GraalVM suporta o chamado programação poliglota na qual diferentes componentes de
uma aplicação podem ser desenvolvidos usando a linguagem mais adequada e então
se combinar perfeitamente em tempo de execução. Dessa forma, uma biblioteca única escrita em, digamos,
Java pode ser usada em uma aplicação node.js escrita em JavaScript, por exemplo.
Para suportar a programação poliglota, a plataforma GraalVM tem suas próprias implementações de alto desempenho
de linguagens populares. Vamos aproveitar isso para
osso projeto de exemplo FreezeCoin para mostrar como é fácil usar sua linguagem preferida.
Antes de executar os exemplos abaixo (em JavaScript, Python e Ruby), por favor, certifique-se de que você tem a
versão Java do FreezeCoin funcionando localmente para garantir que tudo esteja configurado corretamente.
JavaScript
O GraalVM pode executar JavaScript e
Node.js
aplicações prontamente. É compatível com a especificação ECMAScript 2019.
Além disso, os lançadores js e node aceitam opções de linha de comando especiais --jvm e --polyglot
que permitem que scripts JS acessem objetos e classes Java.
Dado que esse é o caso, uma implementação JS do FreezeCoin pode ser facilmente escrita usando a interface API do Appkit.
Por favor, veja o código fonte completo da implementação FreezeCoin JS
para detalhes.
O seguinte comando usa o lançador node para executar o script FreezeCoin.js.
$ node --jvm --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
js-examples/FreezeCoin.js 1000000000
Observe que os caminhos no comando são relativos à raiz do
diretório do projeto ergo-appkit-examples.
Python
O GraalVM pode executar scripts Python, embora
a implementação Python ainda seja experimental (veja também a
seção de compatibilidade
para detalhes).
Exemplo Python do
FreezeCoin
pode ser executado usando o seguinte comando
$ graalpython --jvm --polyglot --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
python-examples/FreezeCoin.py 1900000000
Ruby
O GraalVM pode executar scripts Ruby usando
a implementação TruffleRuby, que ainda é experimental (veja também a
seção de compatibilidade
para detalhes).
A TruffleRuby visa ser totalmente compatível com a implementação padrão do Ruby, MRI, versão 2.6.2
Exemplo Ruby do
FreezeCoin
pode ser executado usando o seguinte comando
$ truffleruby --polyglot --jvm --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
ruby-examples/FreezeCoin.rb 1900000000
4. Bibliotecas Compartilhadas Nativas do Ergo
Outro grande benefício do GraalVM é que podemos compilar classes Java em uma biblioteca compartilhada nativa em vez de um executável.
Para fazer isso, declaramos um ou mais métodos estáticos como @CEntryPoint.
public class FreezeCoin {
...
/**
* Ponto de entrada chamável a partir de C que envolve {@link FreezeCoin#sendTx}
*/
@CEntryPoint(name = "sendTx")
public static void sendTxEntryPoint(
IsolateThread thread,
SignedWord amountToSendW,
CCharPointer configFileNameC,
CCharPointer resBuffer, UnsignedWord bufferSize) throws FileNotFoundException {
long amountToSend = amountToSendW.rawValue();
// Converter as strings C para as strings Java alvo.
String configFileName = CTypeConversion.toJavaString(configFileNameC);
String txJson = sendTx(amountToSend, configFileName);
// colocar a string resultante no buffer fornecido
CTypeConversion.toCString(txJson, resBuffer, bufferSize);
}
...
}
Podemos então compilar para uma biblioteca compartilhada e um arquivo de cabeçalho gerado automaticamente. Note o uso da opção --shared.
$ native-image --no-server \
-cp build/libs/appkit-examples-3.1.0-all.jar\
--report-unsupported-elements-at-runtime\
--no-fallback -H:+TraceClassInitialization -H:+ReportExceptionStackTraces\
-H:+AddAllCharsets -H:+AllowVMInspection -H:-RuntimeAssertions\
--allow-incomplete-classpath \
--enable-url-protocols=http,https
--shared -H:Name=libfreezecoin -H:Path=c-examples
$ otool -L c-examples/libfreezecoin.dylib
c-examples/libfreezecoin.dylib:
.../c-examples/libfreezecoin.dylib (versão de compatibilidade 0.0.0, versão atual 0.0.0)
/usr/lib/libSystem.B.dylib (versão de compatibilidade 1.0.0, versão atual 1252.50.4)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (versão de compatibilidade 150.0.0, versão atual 1455.12.0)
/usr/lib/libz.1.dylib (versão de compatibilidade 1.0.0, versão atual 1.2.11)
Agora temos a capacidade de escrever um programa C
que usa a biblioteca.
A interface para nossa biblioteca nativa tem um pouco de
boilerplate (porque a VM precisa gerenciar um heap, threads, um coletor de lixo
e mais), e assim precisamos criar uma instância e fornecê-la
nossa thread principal.
#include <stdlib.h>
#include <stdio.h>
#include <libfreezecoin.h>
int main(int argc, char **argv) {
graal_isolate_t *isolate = NULL;
graal_isolatethread_t *thread = NULL;
if (graal_create_isolate(NULL, &isolate, &thread) != 0) {
fprintf(stderr, "erro graal_create_isolate\n");
return 1;
}
char * configFileName = "freeze_coin_config.json";
// obter amountToSend dos args cmd e chamar a criação da transação
long amountToSend = atol(argv[1]);
char result[1024 * 16];
sendTx(thread, amountToSend, configFileName, result, sizeof(result));
// imprimir o resultado serializado
printf("%s\n", result);
if (graal_detach_thread(thread) != 0) {
fprintf(stderr, "erro graal_detach_thread\n");
return 1;
}
return 0;
}
Podemos compilar isso com nossas ferramentas de sistema padrão e facilmente executar nosso executável (defina LD_LIBRARY_PATH=. no Linux).
$ clang -Ic-examples -Lc-examples -lfreezecoin c-examples/freezecoin.c -o call_freezecoin
$ otool -L call_freezecoin
$ DYLD_LIBRARY_PATH=$GRAAL_HOME/jre/lib ./call_freezecoin 1000000000
5. Depurando Sua Aplicação Ergo Poliglota
Você pode depurar JS, Python e Ruby no IntelliJ, mas se por algum motivo isso
d não funcionar para você ou não se encaixar com seu editor preferido, o GraalVM oferece outra opção.
Todas as linguagens do GraalVM (exceto Java) são implementadas usando o comum
framework Truffle.
O Truffle permite que ferramentas como depuradores sejam implementadas uma vez e estejam disponíveis
para todas as linguagens suportadas.
Assim, podemos executar nosso programa com a flag --inspect, que nos dará um link para
abrir no Chrome e pausará o programa no depurador.
$ ruby --polyglot --jvm --inspect --vm.cp=build/libs/appkit-examples-3.1.0-all.jar \
ruby-examples/FreezeCoin.rb 1900000000
Depurador ouvindo na porta 9229.
Para começar a depurar, abra a seguinte URL no Chrome:
chrome-devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/30c7da1e-7558a47d09b
...
A partir daqui, podemos definir pontos de interrupção e continuar a execução. Quando ele parar, veremos
os valores das variáveis, podemos continuar novamente até o próximo ponto de interrupção e fazer tudo o que esperamos de depuradores.

Conclusões
E com tudo isso dito e feito, vemos como é fácil usar o Appkit para
desenvolver Aplicações Ergo. O Appkit depende das mesmas bibliotecas centrais exatas que
foram usadas na implementação do protocolo de consenso Ergo. Essas bibliotecas incluem
o compilador ErgoScript, criptografia, interpretador de bytecode, serializadores de dados
e outros componentes centrais. Usando o GraalVM, somos capazes de reutilizar esses componentes testados
e comprovados em diferentes contextos de aplicação sem qualquer modificação
ou reescrevê-los nós mesmos.
Não importa se você está usando Java, JavaScript, Python ou Ruby, você pode aproveitar
o Appkit com o GraalVM para simplificar drasticamente o processo de
interagir com a blockchain Ergo enquanto cria (d)Apps que rodam nativamente.
Fique atento. Em postagens futuras, apresentaremos a você outras aplicações potenciais interessantes
impulsionadas pelo Appkit.
Referências
Share post
13 de agosto de 2025
12 de agosto de 2025
9 de julho de 2025
12 de maio de 2025

7 de abril de 2022

8 de março de 2022


















