npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-pocket-safe

v0.2.1

Published

Pocket-Safe is a decentralized system for secure offline blockchain management, enabling local transactions via Bluetooth, Wi-Fi, NFC, or QR Codes. A fiscal agent ensures integrity through digital signatures, offering scalable and reliable solutions.

Downloads

638

Readme

node-pocket-safe

Pocket-Safe é uma proposta inovadora para um sistema descentralizado que permite o armazenamento e gerenciamento offline de blockchain, com foco em escalabilidade, segurança e acessibilidade. Inspirado em tecnologias modernas, ele introduz o conceito de um agente fiscal que verifica periodicamente a integridade dos blockchains por meio de assinaturas digitais, eliminando a necessidade de armazenar todas as informações em um servidor central.

Este modelo permite transações offline usando métodos de comunicação local, como Bluetooth, Wi-Fi ou NFC, mantendo a segurança e a confiabilidade das transações. Para operações de longa distância, o agente fiscal atua como um intermediário apenas para validar e sincronizar informações.

Ao adotar o conceito Pocket-Safe, esta API fornece ferramentas que aderem aos mesmos princípios de descentralização e escalabilidade, permitindo o gerenciamento confiável de dados com suporte para validação periódica e foco em um modelo baseado em confiança entre os participantes. É ideal para aplicações que exigem operações seguras e descentralizadas.

Sumário

Instalação

Para instalar a API Pocket-Safe, você pode usar no npm ou yarn:

npm install node-pocket-safe

ou

yarn add node-pocket-safe

Uso

Para começar a usar a API Pocket-Safe, você precisa importar o módulo e criar uma instância do PocketSafe, neste momente, terá que escolher qual personagem atuará, se será um agente fiscal ou um participante. Ouse seja, Server ou Client.

Mas, antes de qualquer coisa, ambas instâncias, exigem o uso do base-database para armazenar os dados. Neste caso, não precisaria de instalar o pacote, pois o Pocket-Safe já o faz e o exporta como Database. Mas, será necessário configurar o Database antes de criar a instância do PocketSafe, para isso, consulte a documentação do base-database.

import { Database } from 'node-pocket-safe';

class MyDatabase extends Database {
    // Implementação da classe
}

Criando uma instância do Server como agente fiscal:

import { Server } from 'node-pocket-safe';

const key:string = "..."; // Chave de acesso
const password:string = "..."; // Senha de acesso

function validatePayload(payload: any): boolean {
    // Implementação da função
}

const pocketSafeServer = new Server(key, password, MyDatabase, validatePayload);

Criando uma instância do Client como participante:

import { Client } from 'node-pocket-safe';

const pocketSafeClient = new Client(MyDatabase);

const [ blockchain ] = await pocketSafeClient.listClients(); // Lista todos os clientes

const password:string = "..."; // Senha de acesso
pocketSafeClient.open(blockchain.address, password); // Abre um cliente

Documentação

Como já vimos antes, temos dois personagens, Server e Client. Ambos possuem métodos e propriedades específicas, ao longo da documentação, você poderá ver todas as informações necessárias para usar a API Pocket-Safe.

Criando um novo Client (participante/blockchain)

A primeira coisa que você precisa fazer, é ter um Client para poder interagir com o Server ou outros Clients. Nesse caso, temos duas alternativas, criar um novo Client ou abrir um Client existente. Para criar um novo Client, você pode usar o método create da instância do Client, mas, para isso, antes é preciso ter a chave pública do servidor, ou seja, do agente fiscal, que será chamado de domainPublicKey.

const domainPublicKey:string = "..."; // Chave pública do servidor
const password:string = "..."; // Senha de acesso - inserida pelo usuário

const client = await pocketSafeClient.create(domainPublicKey, password);

Mas ainda não acabou, o método create retorna uma promessa, que, quando resolvida, retorna um objeto com publicKey (chalve pública do Client), confirmationInfo (informações de confirmação inicial já assinada pelo Client), timestamp (número em milissegundos indicando a data do momento de criação), prepareGenesisBlock (método para preparar o bloco genesis) e finish (método para finalizar a criação do Client).

Ou seja, a partir desse momento, teremos que obter algumas informações do servidor para proceguirmos com a criação do cliente. O servidor exifirá do Client o publicKey, confirmationInfo e timestamp para retornar ao cliente os dados que necessita para a criação do bloco genesis. Seão elas, timestamp, payload, confirmation, sign, hash e nonce:

// Obter os dados do servidor. Função fictícia.
const data = await fetchServer("createGenesisBy", client.publicKey, client.confirmationInfo, client.timestamp);

await client.prepareGenesisBlock(data.timestamp, data.payload, data.confirmation, data.sign, data.hash, data.nonce);

Após realizar a etapa de preparação do bloco genesis, o Client estará pronto para ser finalizado, ou seja, para ser adicionado ao Database de forma localmente. Para isso, basta chamar o método finish:

await client.finish();

Observe que, o método finish, só poderá ser útil, se o bloco genesis for preparado corretamente. Caso contrário, ao chamar o método finish antes de preparar o bloco genesis, emitirá um erro, informando que o bloco genesis não foi preparado.

Criando um novo Server (agente fiscal)

Para criar um novo Server, você precisará apenas de criar a chave protegida por senha, que será usada para obter a chave pública e privada do servidor. Para isso, basta chamar o método estático createKey da instância do Server:

import { Server } from 'node-pocket-safe';

const password:string = "..."; // Senha de acesso
const key:string = Server.createKey(password);

Será preciso armazenar a chave em um local seguro, pois, sem ela, não será possível acessar o servidor. Além disso, a chave será usada para criar a instância do Server:

const pocketSafeServer = new Server(key, password, MyDatabase, validatePayload);

Cliente - Blockchain

O Client é o participante de uma rede, ou seja, no conceito Pocket-Safe, ele é a blockchain. O Client é responsável por realizar transações, receber transações, verificar a confiabilidade da blockchain, sincronizar os blocos com o servidor e outros clientes, entre outras funções. Para realizar essas funções, o Client fornece métodos e propriedades específicas.

Remetente (offline)

Um remetente é um cliente que deseja realizar uma transação com outro cliente, ou seja, o beneficiário. Para isso, ele precisará de algumas informações do beneficiário, como a chave pública e o confirmation gerado pelo beneficiário. O primeiro passa é trânsmitir para o beneficiário a chave pública e dados internos com assinatura da rede do remetente. Para obter a chave pública e dados internos do remetente, basta chamar os métodos publicKey e internalGenesis da instância do Client:

const sendingPublicKey:string = sendingClient.publicKey;
const sendingInternalGenesis:any = sendingClient.internalGenesis;

// Enviar a chave pública para o beneficiário
// Função fictícia
sendToBeneficiary("publicKey", sendingPublicKey, sendingInternalGenesis);

Logo em seguida, o beneficiário receberá a chave pública do remetente e poderá gerar o confirmation para o remetente.

Após o beneficiário gerar o confirmation, o remetente receberá o confirmation do beneficiário e poderá realizar a transação. Para isso, basta chamar o método fromBeneficiary da instância do Client:

// Receber a chave pública e o confirmation do beneficiário
// Função fictícia
const [beneficiaryPublicKey, beneficiaryConfirmation] = await receiveFromBeneficiary("confirmation");

const payload:any = {...}; // Dados da transação

const blockForBeneficiary = await sendingClient.fromBeneficiary(beneficiaryPublicKey, beneficiaryConfirmation, payload);

// Enviar o bloco para o beneficiário
// Função fictícia
sendToBeneficiary("block", blockForBeneficiary);

Após chamar o método fromBeneficiary, o remetente criará um bloco com os dados da transação e o enviará para o beneficiário. O beneficiário poderá verificar a transação e, se estiver tudo certo, poderá incluir o bloco na sua blockchain.

Todo esse processo poderá ser simplificado usando o método createSender, ele cria as etapas necessárias para a realizar a transação entre remetente e beneficiário. Seus parâmetros são o payload da transação e uma callback que será chamada em cada estágio, essa callback recebe uma string em base64 que deve ser enviado para o beneficiário, isso se o beneficiário estiver usando o método createBeneficiary. O método createSender retorna uma promessa que, quando resolvida, retorna uma função que deverá ser chamada a cada resposta do beneficiário:

const payload:any = {...}; // Dados da transação

const receiveFromBeneficiary = await pocketSafeClient.createSender(payload, (data) => {
    receiveFromSender(data);
});

Nota: Recomendamos a utilização dos métodos createSender e createBeneficiary. São métodos prontos para realizar transações entre remetente e beneficiário. Eles simplificarão o processo de transação e garantirão a confiabilidade da blockchain.

Remetente (online)

Para realizar uma transação entre remetente e beneficiário a distância, será necessário usar o servidor como intermediário. Nesse caso, temos o método parecido como o createSender, que é o createSenderForAddress. Ele cria as etapas necessárias para a realizar a transação entre remetente e beneficiário a distância usando o servidor como intermediário. Seus parâmetros são o address do beneficiário, o payload da transação e uma callback que será chamada em cada estágio, essa callback recebe uma string em base64 que deve ser enviado para o servidor. O método createSenderForAddress retorna uma promessa que, quando resolvida, retorna uma função que deverá ser chamada a cada resposta do servidor:

const address:string = "..."; // Endereço do beneficiário
const payload:any = {...}; // Dados da transação

const receiveFromServer = await pocketSafeClient.createSenderForAddress(address, payload, (data) => {
    // Função fictícia
    receiveFromSender(data);
});

Beneficiário (offline)

Um beneficiário é um cliente que deseja receber uma transação de outro cliente, ou seja, o remetente. Para isso, ele precisará da chave pública do remetente. O primeiro passa é receber a chave pública do remetente e usar o método getConfirmation da instância do Client para gerar o confirmation, que será enviado para o remetente. Mas antes disso, será necessário verificar o internalGenesis recebido jundo com a chave pública do remetente:

// Receber a chave pública do remetente
// Função fictícia
const [sendingPublicKey, sendingInternalGenesis] = await receiveFromSender("publicKey");

const isValid:boolean = await beneficiaryClient.verifyInternalGenesis(sendingPublicKey, sendingInternalGenesis);

const beneficiaryConfirmation = await beneficiaryClient.getConfirmation(sendingPublicKey);

// Enviar o confirmation para o remetente
// Função fictícia
sendToSender("confirmation", beneficiaryClient.publicKey, beneficiaryConfirmation);

A verificação do internalGenesis é importante para garantir que o remetente é confiável. Após a verificação, o beneficiário poderá gerar o confirmation e enviar para o remetente.

O remetente receberá o confirmation e poderá realizar a transação. Após o remetente realizar a transação, o beneficiário receberá o bloco da transação e poderá verificar se está tudo certo. Se estiver, poderá incluir o bloco na sua blockchain. Isso é feito chamando o método fromSender da instância do Client:

// Receber o bloco do remetente
// Função fictícia
const blockForBeneficiary = await receiveFromSender("block");

await beneficiaryClient.fromSender(blockForBeneficiary);

Assim como já vimos antes usando o método createSender, o beneficiário poderá usar o método createBeneficiary para simplificar o processo de transação entre remetente e beneficiário. Requer apenas um parâmetro, que é uma callback que será chamada em cada estágio, essa callback recebe uma string em base64 que deve ser enviado para o remetente. O método createBeneficiary retorna uma promessa que, quando resolvida, retorna uma função que deverá ser chamada a cada resposta do remetente:

const receiveFromSender = await pocketSafeClient.createBeneficiary((data) => {
    receiveFromBeneficiary(data);
});

Nota: Recomendamos a utilização dos métodos createSender e createBeneficiary. São métodos prontos para realizar transações entre remetente e beneficiário. Eles simplificarão o processo de transação e garantirão a confiabilidade da blockchain.

É importante ressaltar que, estamos apenas vendo como usar os métodos da instância do Client. Para realizar o trâmite de comunicação entre remetente e beneficiário, será necessário usar métodos de comunicação local, como Bluetooth, Wi-Fi ou NFC. Isso se falando de dispositivos móveis diferentes, mas, se falando de dispositivos desktop, poderá ser usado métodos de comunicação local, como WebSocket. A escolha do método de comunicação dependerá do desenvolvedor. A proposta dessa API é apenas fornecer as ferramentas necessárias para realizar o conceito Pocket-Safe.

Beneficiário (online)

Para receber uma transação do remetente a distância, será necessário usar o servidor como intermediário. Nesse caso, temos o método parecido como o createBeneficiary, que é o checkReceiptPending. Ele cria as etapas necessárias para a receber as transações pendentes. Ele requer apenas um parâmetro, que é uma callback que será chamada em cada estágio, essa callback recebe uma string em base64 que deve ser enviado para o servidor. O método checkReceiptPending retorna uma promessa que, quando resolvida, retorna uma função que deverá ser chamada a cada resposta do servidor:

const receiveFromServer = await pocketSafeClient.checkReceiptPending((data) => {
    // Função fictícia
    receiveFromBeneficiary(data);
});

Se caso não houver transações pendentes, o método checkReceiptPending retornará um erro informando que não há transações pendentes.

Observe que, o método checkReceiptPending opera uma transação pendentente por vez. Se houver mais de uma transação pendente, será necessário chamar o método checkReceiptPending novamente para verificar a próxima transação pendente.

Confiabilidade

A confiabilidade é um dos pontos mais importantes da API Pocket-Safe. Para garantir a confiabilidade, a API Pocket-Safe fornece um método para verificar a integridade da blockchain por através de assinaturas digitais, em especial, a assinatura digital do agente fiscal. A assinatura digital do agente fiscal é obtido após a sincronização dos blocos entre servidor e cliente. Isso é fundamental na hora de realizar transações, pois, se a assinatura digital do agente fiscal não estiver conforme o esperado, a transação não será realizada, pois, poderá ser regeitada por um dos participantes. Porém, isso só servirá se caso usar os métodos createSender e createBeneficiary. Para verificação da confiabilidade, basta definir no método reliability da instância do Client, seu valor deverá ser entre 0 e 1, sendo que, quando mais perto de 1, mais confiável deverá ser a blockchain:

pocketSafeClient.reliability = 0.9; // Confiabilidade de 90%

A verificação da confiabilidade é feita automaticamente pela API Pocket-Safe com a utilização dos métodos createSender e createBeneficiary. Durante a transação, é feito o cálculo da confiabilidade em base na ultima data em que o agente fiscal sincronizou com o cliente, com sua assinatura atualizada para confirmação da integridade dos blocos. Se a confiabilidade for menor que o valor definido, a transação poderá ser rejeitada. Em casos espesíficos, se caso a confiabilidade for assima de 0.70 e abaixo do valor definido, o usuário poderá ser notificado para que ele possa decidir se pretende realizar/receber a transação ou não, se caso a confiabilidade for abaixo de 0.70, a transação será rejeitada automaticamente se caso a confiabilidade for abaixo do valor definido.

Nota: A confiabilidade é calculada em base na assinatura digital do agente fiscal e na data da última sincronização entre servidor e cliente.

Para saber a confiabilidade da blockchain, basta chamar o método getReliability da instância do Client. O método getReliability retornará um número entre 0 e 1, sendo que, quanto mais perto de 1, mais confiável seria a blockchain:

const reliability:number = pocketSafeClient.getReliability();

Sinconização

Para evitar problemas durante as transações, é crusial que os blocos estejam sincronizados entre servidor e cliente. Para isso, a API Pocket-Safe fornece um método para sincronizar os blocos entre servidor e cliente. Essa parte é fundamenta para garantir a integridade dos blocos e a confiabilidade das transações. A integridade dos blocos é medita com base na assinatura digital do agente fiscal, que é responsável em validar cada bloco. Se um bloco se quer estiver fora de ordem ou que possa levantar suspeitas, o servidor poderá se recusar a atualizar sua assinatura digital, o que poderá levar a baixa confiabilidade da blockchain. Ou seja, sem a assinatura digital do agente fiscal atualizada, as transações podem não ser realizadas conforme o nível de confiabilidade esperado.

Para sincronizar os blocos, temos muitos métodos importantes para serem usados entre servidor e cliente. Do lado do cliente, temos o método syncBlockchain da instância do Client, que iniciará o processo de sincronização, percorrendo cada bloco da blockchain e enviando ao servidor:

// Um listener para receber os blocos de sincronização e enviar ao servidor
pocketSafeClient.on('chunkBlock', (block, index, length, confirm) => {
	console.log(`Syncing block ${index + 1}/${length}`);
    // Implementação
    // Função fictícia
    fetchServer("syncBlockchain", block).then(confirm);
});

pocketSafeClient.syncBlockchain()  // Inicia a sincronização
.then(({ publicKey, confirmation })=>{
    fetchServer("getSignatureBy", publicKey, confirmation) // Obtem a assinatura do servidor
    .then((payload) => {
        pocketSafeClient.updateServerSignature(payload); // Atualiza a assinatura do servidor
    });
});

Servidor - Agente Fiscal

Para assegurar a integridade das blockchains no conceito Pocket-Safe, seria necessário introduzir um agente fiscal, que, na prática, seria representado por um servidor denominado "rede". Essa rede desempenharia funções cruciais, como gerar os blocos gênese, verificar a integridade dos blocos da blockchain durante a etapa de sincronização, atualizar sua assinatura gênese para validar a consistência da cadeia, além de atuar como intermediário no envio e recebimento de blocos entre remetentes e beneficiários a longa distância.

Criar bloco gênese

Para criar um bloco gênese, basta chamar o método createGenesisBy da instância do Server. O método createGenesisBy requer os parâmetros publicKey e confirmation do cliente e timestamp da data de criação do bloco gênese:

const publicKey:string = "..."; // Chave pública do cliente
const confirmation:ConfirmationBlock = {...}; // Confirmação do cliente
const timestamp:number = Date.now(); // Data de criação do bloco gênese

const genesisBlock = await pocketSafeServer.createGenesisBy(publicKey, confirmation, timestamp);

O método createGenesisBy retornará um objeto com os dados do bloco gênese, como timestamp, payload, confirmation, sign, hash e nonce. Esses dados serão usados pelo cliente para preparar o bloco gênese. Ou seja, sua função é receber do cliente a chave pública e a confirmação, gerar as informações que o cliente precisa para preparar o bloco gênese e enviar para o cliente.

Sinconização

Para sincronizar os blocos, temos muitos métodos importantes para serem usados entre servidor e cliente. Do lado do servidor, temos o método syncBlockchain da instância do Server, que bloco por bloco da blockchain recebido do cliente e verifica a integridade de cada bloco:

// Exemplo por parte do servidor
const syncBlock = async (block) => {
    await pocketSafeServer.syncBlockchain(block); // Verifica a integridade do bloco
};

// Exemplo por parte do cliente
pocketSafeClient.on('chunkBlock', (block, index, length, confirm) => {
    // Implementação
    syncBlock(block) // Envia o bloco para o servidor
    .then(confirm); // Se não houver erros, confirma o bloco
});

Como vemos nesse exemplo, o cliente envia os blocos para o servidor e o servidor verifica a integridade de um bloco específico por vez. Se um bloco estiver fora de ordem ou que possa levantar suspeitas, o servidor emite um erro informando que o bloco não é válido e o processo de sincronização é interrompido, ou seja, o servidor se recusa a atualizar sua assinatura digital, o que poderá levar a baixa confiabilidade da blockchain.

No exemplo, como que o código por parte do servidor e cliente estão num mesmo arquivo de código. O ideal sia usar métodos de comunicação web, como WebSocket, para realizar a sincronização entre servidor e cliente. O servidor poderá enviar os blocos para o cliente e o cliente poderá enviar os blocos para o servidor. A escolha do método de comunicação dependerá do desenvolvedor. A proposta dessa API é apenas fornecer as ferramentas necessárias para realizar o conceito Pocket-Safe.

Atualizar assinatura

Para atualizar a assinatura do servidor após realizar o processo de sincronização e todos os blocos estiverem corretos, basta chamar o método getSignatureBy da instância do Server. O método getSignatureBy requer os parâmetros publicKey e confirmation do cliente:

// Exemplo por parte do servidor
const getSignature = async (publicKey, confirmation) => {
    return await pocketSafeServer.getSignatureBy(publicKey, confirmation); // Gera a assinatura atualizada do servidor
};

// Exemplo por parte do cliente
pocketSafeClient.syncBlockchain()  // Inicia a sincronização
.then(({ publicKey, confirmation })=>{
    getSignature(publicKey, confirmation) // Obtem a assinatura do servidor
    .then((payload) => {
        pocketSafeClient.updateServerSignature(payload); // Atualiza a assinatura do servidor
    });
});

O método getSignatureBy retornará um objeto com os dados da assinatura do servidor que serão usados pelo cliente para atualizar a assinatura do servidor. Ou seja, sua função é receber do cliente a chave pública e a confirmação, gerar a assinatura atualizada do servidor e enviar para o cliente. Porá resultar em erros em caso de falha na sincronização dos blocos ou se não houver executado a sincronização dos blocos antes de chamar o método getSignatureBy.

Intermediação - Remetente

Para realizar uma transação entre remetente e beneficiário a longa distância, será necessário usar o servidor como intermediário. Nesse caso, temos o método parecido como o createSenderForAddress, que é o sendToAddress da instância do Server. Ele cria as etapas necessárias para a realizar a transação entre remetente e beneficiário a distância usando o servidor como intermediário. O método requer apenas um parâmetro, que é data, uma string em base64 que recebe do remetente por através de método createSenderForAddress. O método sendToAddress retorna uma promessa que, quando resolvida, retorná uma string em base64 que deverá ser enviada para o beneficiário:

// Exemplo por parte do servidor
const receiveFromSender = async (data) => {
    return await pocketSafeServer.sendToAddress(data); // Recebe o data do remetente, processa e retorna um data para o remetente
};

// Exemplo por parte do cliente
const address:string = "..."; // Endereço do beneficiário
const payload:any = {...}; // Dados da transação

const receiveFromServer = await pocketSafeClient.createSenderForAddress(address, payload, (data) => { // Cria o sender para o servidor
    receiveFromSender(data) // Envia o data para o servidor
    .then(receiveFromServer); // Recebe o data do servidor
});

Caso a transação pendente seja realizado, o servidor dispara um evento listener pendingReceipt, que poderá ser usado para notificar o beneficiário que há transação pendente. O beneficiário poderá usar o método receiveToAddress para verificar e receber a transação pendente e, se estiver tudo certo, poderá incluir o bloco na sua blockchain.

// Exemplo por parte do cliente
const receivePending = await ()=>{ // Função para receber a transação pendente
    // Implementação
}

// Exemplo por parte do servidor
pocketSafeServer.on('pendingReceipt', (fromAddress) => {
    // Implementação
    if (fromAddress === pocketSafeClient.address) { // Verifica se a transação é do beneficiário
        receivePending(); // Recebe a transação pendente
    }
});

Intermediação - Beneficiário

Para receber uma transação do remetente a distância, será necessário usar o servidor como intermediário. Nesse caso, temos o método parecido como o sendToAddress, que é o receiveToAddress da instância do Server. Ele tem a mesma função que o sendToAddress, mas, para em caso de transação pendente. O método requer apenas um parâmetro, que é data, uma string em base64 que recebe do beneficiário por através de método checkReceiptPending. O método receiveToAddress retorna uma promessa que, quando resolvida, retorná uma string em base64 que deverá ser enviada para o beneficiário:

// Exemplo por parte do servidor
const receiveFromBeneficiary = async (data) => {
    return await pocketSafeServer.receiveToAddress(data); // Recebe o data do beneficiário, processa e retorna um data para o beneficiário
};

// Exemplo por parte do cliente
const receiveFromServer = await pocketSafeClient.checkReceiptPending((data) => { // Verifica a transação pendente e o recebe
    receiveFromBeneficiary(data) // Envia o data para o servidor
    .then(receiveFromServer); // Recebe o data do servidor
});

Criar uma transação pendente

Haverá casos em que o servidor possa querer enviar uma transação pendente para o beneficiário, fazendo o papel de remetente. Para isso, basta chamar o método createSubmission da instância do Server. O método createSubmission requer os parâmetros address do beneficiário e payload da transação:

const address:string = "..."; // Endereço do beneficiário
const payload:any = {...}; // Dados da transação

await pocketSafeServer.createSubmission(address, payload);

Solicitar cobrança

Haverá casos em que o servidor possa querer solicitar uma cobrança de um cliente, fazendo o papel de beneficiário. Para isso, basta chamar o método requestCharge da instância do Server. O método requestCharge requer os parâmetros address do cliente e payload da transação:

const address:string = "..."; // Endereço do cliente
const payload:any = {...}; // Dados da transação

await pocketSafeServer.requestCharge(address, payload);

API

A API Pocket-Safe fornece métodos e propriedades específicas para cada personagem, Server e Client. Abaixo, você poderá ver todos os métodos e propriedades disponíveis com suas definições e tipagem.

Server

Uma instância do Server é um agente fiscal que verifica a integridade dos blocos da blockchain, atualiza sua assinatura digital para validar a consistência da cadeia, além de atuar como intermediário no envio e recebimento de blocos entre remetentes e beneficiários a longa distância.

Métodos

  • constructor(key: string, password: string, database: typeof Database, validatePayload: (payload: any) => boolean): Cria uma instância do Server.
    • key: string: Chave protegida por senha.
    • password: string: Senha de acesso.
    • database: typeof Database: Classe do Database.
    • validatePayload: (payload: any) => boolean: Função para validar o payload, usado durante a sincronização dos blocos, ou seja, no método syncBlockchain.
  • createGenesisBy(publicKey: string, confirmation: ConfirmationBlock, timestamp: number): Promise<{ timestamp: number; payload: ConfirmationBlock["internal"]; confirmation: ConfirmationBlock; sign: string; hash: string; nonce: number; }>: Cria um bloco gênese.
    • publicKey: string: Chave pública do cliente.
    • confirmation: ConfirmationBlock: Confirmação do cliente.
    • timestamp: number: Data de criação do bloco gênese.
    • Retorno: Objeto com os dados do bloco gênese.
  • syncBlockchain(block: Block): Promise<void>: Sincroniza os blocos.
    • block: Block: Bloco a ser sincronizado.
    • Retorno: Sem retorno.
  • getSignatureBy(publicKey: string, confirmation: ConfirmationBlock): Promise<SignatureBlock>: Atualiza a assinatura.
    • publicKey: string: Chave pública do cliente.
    • confirmation: ConfirmationBlock: Confirmação do cliente.
    • Retorno: Objeto com os dados da assinatura.
  • sendToAddress(data: string): Promise<string>: Envia um bloco para um endereço.
    • data: string: Dado do processo de transação.
    • Retorno: Dado para o processo de transação.
  • receiveToAddress(data: string): Promise<string>: Recebe um bloco pendente para um endereço.
    • data: string: Dado do processo de transação.
    • Retorno: Dados para o processo de transação.
  • createSubmission(address: string, payload: any): Promise<void>: Cria uma transação pendente.
    • address: string: Endereço do beneficiário.
    • payload: any: Dados da transação.
    • Retorno: Sem retorno.
  • requestCharge(address: string, payload: any): Promise<void>: Solicita uma cobrança.
    • address: string: Endereço do cliente.
    • payload: any: Dados da transação.
    • Retorno: Sem retorno.

Listeners

  • pendingReceipt: (fromAddress: string) => void: Evento para notificar que há transação pendente. É convocado quando o servidor recebe um bloco pendente de um cliente, ou seja, após a finalização do processo de transação no método sendToAddress.
    • fromAddress: string: Endereço do beneficiário.

Client

Uma instância do Client é um participante de uma rede, ou seja, no conceito Pocket-Safe, ele é a blockchain. O Client é responsável por realizar transações, receber transações, verificar a confiabilidade da blockchain, sincronizar os blocos com o servidor e outros clientes, entre outras funções.

Métodos

  • constructor(database: typeof Database): Cria uma instância do Client.
    • database: typeof Database: Classe do Database.
    • Retorno: Sem retorno.
  • listServers(): Promise<Array<{ name: string; address: string; }>>: Lista os servidores.
    • Retorno: Uma promessa com um array de objetos contendo os dados simples dos servidores.
      • name: string: Nome do servidor.
      • address: string: Endereço do servidor.
  • addServer(name: string, publicKey: string, api: string, version: string): Promise<void>: Adiciona um servidor ou substitui um servidor existente.
    • name: string: Nome do servidor.
    • publicKey: string: Chave pública do servidor.
    • api: string: Endereço da API do servidor.
    • version: string: Versão da API do servidor.
    • Retorno: Sem retorno.
  • removeServer(address: string): Promise<void>: Remove um servidor.
    • address: string: Endereço do servidor.
    • Retorno: Sem retorno.
  • getServerInfo(address: string): Promise<ServerInfo | undefined>: Obtem as informações de um servidor.
    • address: string: Endereço do servidor.
    • Retorno: Uma promessa com as informações do servidor ou undefined se o servidor não existir.
      • name: string: Nome do servidor.
      • publicKey: string: Chave pública do servidor.
      • api: string: Endereço da API do servidor.
      • version: string: Versão da API do servidor.
      • address: string: Endereço do servidor.
  • listClients(): Promise<Array<{ name: string; address: string; }>>: Lista os clientes.
    • Retorno: Uma promessa com um array de strings contendo as chaves públicas dos clientes.
      • name: string: Nome do cliente.
      • address: string: Endereço do cliente.
  • create(domainPublicKey: string, password: string): Promise<{ publicKey: string; confirmationInfo: ConfirmationBlock; timestamp: number; prepareGenesisBlock(timestamp: number, payload: any, confirmation: ConfirmationBlock, sign: string, hash: string, nonce: number): Promise<void>; finish(oppened?: boolean): Promise<Client | void>; }>: Cria um novo Client.
    • domainPublicKey: string: Chave pública do servidor.
    • password: string: Definição de senha de acesso ao Client.
    • Retorno: Uma promessa com um objeto com os dados do Client e métodos para preparar o bloco genesis e finalizar a criação do Client.
      • publicKey: string: Chave pública do Client.
      • confirmationInfo: ConfirmationBlock: Informações de confirmação inicial já assinada pelo Client.
      • timestamp: number: Número em milissegundos indicando a data do momento de criação.
      • prepareGenesisBlock(timestamp: number, payload: any, confirmation: ConfirmationBlock, sign: string, hash: string, nonce: number): Promise<void>: Prepara o bloco genesis.
        • timestamp: number: Data de criação do bloco gênese.
        • payload: any: Dados do bloco gênese.
        • confirmation: ConfirmationBlock: Confirmação do bloco gênese.
        • sign: string: Assinatura do bloco gênese.
        • hash: string: Hash do bloco gênese.
        • nonce: number: Número de tentativas para encontrar o hash do bloco gênese.
        • Retorno: Sem retorno.
      • finish(oppened?: boolean): Promise<Client | void>: Finaliza a criação do Client.
        • oppened: boolean: Indica se o Client deve ser aberto após a criação bem sucedida.
        • Retorno: Uma promessa com o Client ou sem retorno.
  • open(address: string, password: string): Promise<void>: Abre o Client existente.
    • address: string: Endereço do Client.
    • password: string: Senha de acesso ao Client.
    • Retorno: Sem retorno.
  • close(): Promise<void>: Fecha o Client aberto.
    • Retorno: Sem retorno.
  • server: ServerInfo | undefined: Informações do servidor.
  • address: string | undefined: Endereço do Client.
  • publicKey: string | undefined: Chave pública do Client.
  • name: string | undefined: Nome do Client.
  • internalGenesis: any | undefined: Dados internos do bloco gênese.
  • verifyInternalGenesis(publicKey: string, internalGenesis: any): Promise<boolean>: Verifica o bloco gênese.
    • publicKey: string: Chave pública do responsável pelo internalGenesis.
    • internalGenesis: any: Dados internos do bloco gênese.
    • Retorno: Uma promessa com um booleano indicando se o bloco gênese é válido.
  • getConfirmation(publicKey: string): Promise<ConfirmationBlock>: Gera a confirmação do cliente atual para um cliente específico.
    • publicKey: string: Chave pública do cliente a receber a confirmação.
    • Retorno: Uma promessa com a confirmação.
  • fromBeneficiary<D extends any = LiteralObjJSON>(publicKey: string, confirmation: ConfirmationBlock, data: D): Promise<Block<D>>: Crie um novo bloco para o beneficiário.
    • publicKey: string: Chave pública do beneficiário.
    • confirmation: ConfirmationBlock: Confirmação do beneficiário.
    • data: D: Dados da transação.
    • Retorno: Uma promessa com o bloco da transação.
  • fromSender<D extends any = LiteralObjJSON>(block: Block<D>): Promise<void>: Recebe um bloco do remetente.
    • block: Block<D>: Bloco da transação.
    • Retorno: Sem retorno.
  • payload: ConfirmationBlock["internal"]): { reliability: number; required: number; passable: boolean; }: Confiabilidade do cliente.
    • payload: ConfirmationBlock["internal"]: Dados internos do bloco.
    • Retorno: Objeto com a confiabilidade do cliente.
      • reliability: number: Confiabilidade do cliente.
      • required: number: Confiabilidade mínima requerida.
      • passable: boolean: Indica se a confiabilidade ultrapassou o mínimo requerido.
  • getReliability(): number: Obtém a confiabilidade do cliente.
    • Retorno: Número indicando a confiabilidade do cliente.
  • createSender<D extends any = LiteralObjJSON>( payload: D, callback: (data: string) => void | Promise<void>, trustPermission?: (reliability: number, required: number) => boolean | Promise<boolean>, ): Promise<(data: string) => Promise<void>>: Cria um processo para remetente.
    • payload: D: Dados da transação.
    • callback: (data: string) => void | Promise<void>: Função de retorno para cada estágio para responder ao beneficiário.
    • trustPermission: (reliability: number, required: number) => boolean | Promise<boolean>: Função chamada quando a confiabilidade é menor que o mínimo requerido, deve retornar true para permitir a transação mesmo assim.
    • Retorno: Uma promessa com uma função para cada resposta do beneficiário.
  • createBeneficiary<D extends any = LiteralObjJSON>( callback: (data: string) => void | Promise<void>, trustPermission?: (reliability: number, required: number) => boolean | Promise<boolean>, ): Promise<(data: string) => Promise<void>>: Cria um processo para beneficiário.
    • callback: (data: string) => void | Promise<void>: Função de retorno para cada estágio para responder ao remetente.
    • trustPermission: (reliability: number, required: number) => boolean | Promise<boolean>: Função chamada quando a confiabilidade é menor que o mínimo requerido, deve retornar true para permitir o recebimento da transação mesmo assim.
    • Retorno: Uma promessa com uma função para cada resposta do remetente.
  • createSenderForAddress<D extends any = LiteralObjJSON>(forAddress: string, payload: D, callback: (data: string) => void | Promise<void>): Promise<(data: string) => Promise<void>>: Cria um processo para remetente a distância.
    • forAddress: string: Endereço do beneficiário.
    • payload: D: Dados da transação.
    • callback: (data: string) => void | Promise<void>: Função de retorno para cada estágio para responder ao servidor.
    • Retorno: Uma promessa com uma função para cada resposta do servidor.
  • checkReceiptPending(callback: (data: string) => void | Promise<void>): Promise<(data: string) => Promise<void>>: Verifica e recebe uma transação pendente.
    • callback: (data: string) => void | Promise<void>: Função de retorno para cada estágio para responder ao servidor.
    • Retorno: Uma promessa com uma função para cada resposta do servidor.
  • forEach<D extends any = LiteralObjJSON>(callback: (payload: SimplePayload<D>, index: number, length: number) => void | boolean | Promise<void | boolean>): Promise<void>: Itera sobre cada bloco da blockchain.
    • callback: (payload: SimplePayload<D>, index: number, length: number) => void | boolean | Promise<void | boolean>: Função de retorno para cada bloco.
    • Retorno: Sem retorno.
  • pagination<D extends any = LiteralObjJSON>(skip: number, take: number): Promise<Array<SimplePayload<D>>>: Paginação dos blocos da blockchain.
    • skip: number: Número de blocos a serem ignorados.
    • take: number: Número de blocos a serem retornados.
    • Retorno: Uma promessa com um array de blocos.
  • syncBlockchain(): Promise<{ publicKey: string; confirmation: ConfirmationBlock }>: Sincroniza os blocos com o servidor.
    • Retorno: Uma promessa com a chave pública e a confirmação do servidor.
  • confirmChunkBlock(block: Block): void: Confirma um bloco sincronizado.
    • block: Block: Bloco sincronizado.
    • Retorno: Sem retorno.
  • updateServerSignature(payload: any): Promise<void>: Atualiza a assinatura do servidor.
    • payload: any: Dados da assinatura do servidor.
    • Retorno: Sem retorno.

Listeners

  • create: (info: { address: string; name: string; publicKey: string }) => void: Evento para notificar que um cliente foi criado. É convocado quando um cliente é criado com sucesso.
    • info: { address: string; name: string; publicKey: string }: Informações do cliente criado.
      • address: string: Endereço do cliente.
      • name: string: Nome do cliente.
      • publicKey: string: Chave pública do cliente.
  • open: (scope: Client) => void;: Evento para notificar que um cliente foi aberto. É convocado quando um cliente é aberto com sucesso.
    • scope: Client: Instância do Client aberto.
  • close: () => void;: Evento para notificar que um cliente foi fechado. É convocado quando um cliente é fechado com sucesso.
  • chunkBlock: (block: Block, index: number, length: number, confirm: () => void) => void: Evento para notificar que um bloco foi sincronizado. É convocado quando um bloco é sincronizado com sucesso.
    • block: Block: Bloco sincronizado.
    • index: number: Índice do bloco sincronizado.
    • length: number: Número total de blocos a serem sincronizados.
    • confirm: () => void: Função para confirmar o bloco sincronizado.
  • confirmChunkBlock: (block: Block | undefined) => void: Evento para notificar que um bloco sincronizado foi confirmado. É convocado quando um bloco sincronizado é confirmado com sucesso.
    • block: Block | undefined: Bloco sincronizado.
  • synchronizationProgress: (progress: number) => void: Evento para notificar o progresso da sincronização. É convocado quando um bloco é sincronizado com sucesso.
    • progress: number: Progresso da sincronização.
  • synchronizationError: (error: Error) => void: Evento para notificar um erro na sincronização. É convocado quando um erro ocorre durante a sincronização.
    • error: Error: Erro ocorrido durante a sincronização.
  • syncronizationFinish: (publicKey: string, confirmation: ConfirmationBlock) => void: Evento para notificar que a sincronização foi finalizada. É convocado quando a sincronização é finalizada com sucesso.
    • publicKey: string: Chave pública do servidor.
    • confirmation: ConfirmationBlock: Confirmação do servidor.
  • createBlock: <D extends any = LiteralObjJSON>(block: Block<D>) => void: Evento para notificar que um bloco foi criado. É convocado quando um bloco é criado com sucesso.
    • block: Block<D>: Bloco criado.