WEB3DEV

Cover image for Implementando (Recuperação Social) na Polkadot
Jhonattan Farias
Jhonattan Farias

Posted on

Implementando (Recuperação Social) na Polkadot

Introdução

Neste tutorial, abordaremos como configurar e utilizar a recuperação social para uma conta proxy Polkadot. Este tutorial pressupõe que o leitor tenha um conhecimento prático de JavaScript e Node JS. Embora não seja necessário, seria útil ter passado pelo Polkadot Pathway, que apresenta a API Polkadot JS.

A recuperação social não substitui uma chave privada perdida ou frase inicial (é sempre importante protegê-los). Esse recurso permitirá apenas que o proprietário da conta envie transações em nome da conta perdida para a qual a chave privada e a frase inicial não estão disponíveis - possivelmente devido a perda ou até mesmo uma incapacidade temporária de acessar a conta.

Como esse é um meio pelo qual o acesso aos seus fundos pode ser comprometido, é extremamente importante escolher adequadamente seus contatos de recuperação social.

  • Certifique-se de que qualquer pessoa que você selecionar como contato de recuperação social seja confiável e provavelmente esteja disponível caso você precise de ajuda para recuperar o acesso a uma conta perdida.

  • Seja claro ao definir a expectativa de que, quando você solicitar, que eles iniciem a transação de comprovação, eles sejam capazes de realizar essa tarefa em um período de tempo razoável, bem como se comunicar de volta quando o fizerem.

  • Os contatos de recuperação social devem sempre ser tratados com respeito, pois eles decidem nossa capacidade de acessar a conta caso precisemos usar essa funcionalidade.

  • Os contatos de recuperação social não devem se conhecer ou saber quantas pessoas compõem a lista de recuperação para evitar qualquer risco de conluio - No mínimo, qualquer pessoa na lista precisa saber qual é sua função e como desempenhá-la quando chamada.

Para os fins deste tutorial, assumiremos o papel de todas as partes envolvidas como meio de demonstrar o código relevante. Cabe aos desenvolvedores transferir esse conhecimento para um ambiente de produção de maneira responsável, mantendo as melhores práticas e a segurança do usuário final em mente.

Ao longo deste tutorial, quando ... aparece em um bloco de saída, isso indica que o texto foi cortado para facilitar a leitura. Além disso, a saída do terminal ao executar o código localmente será um pouco diferente dos exemplos, portanto, não se preocupe muito se eles não corresponderem.

Configurar

A execução dessas etapas de configuração para fins de acompanhamento do tutorial não deve ser interpretada como a única maneira de implementar a recuperação social. Este destina-se exclusivamente a permitir que os leitores cheguem a um produto mínimo viável, abordando todos os tipos de transações relevantes. Este tutorial tem duas dependências:

Quando copiamos e colamos todos esses quatro comandos em um terminal, os três primeiros serão executados em sequência. npm init -y produzirá o conteúdo do package.json padrão para o terminal. npm install estará na linha de comando, porém ainda devemos pressionar enter para iniciar o processo de instalação

mkdir polkadot_sr
cd polkadot_sr
npm init -y
npm install --save dotenv @polkadot/api
Enter fullscreen mode Exit fullscreen mode

Após a conclusão do processo de instalação, crie um arquivo .env no diretório do projeto
(/polkadot_sr). Para facilitar, copie e cole o modelo abaixo. Leia mais sobre o dotenv em nosso prático guia de referência rápida. Além disso, lembre-se de substituir API_KEY por uma chave de API DataHub válida no Painel de Serviços do Polkadot.

DATAHUB_URL=http://polkadot-westend--rpc.datahub.figment.io/apikey/API_KEY

ALICE_ADDRESS=
ALICE_MNEMONIC= 

PROXY_ADDRESS=
PROXY_MNEMONIC=

BOB_ADDRESS=
BOB_MNEMONIC=

CHARLIE_ADDRESS= 
CHARLIE_MNEMONIC=
Enter fullscreen mode Exit fullscreen mode

Criar 4 contas

Crie um arquivo chamado create_account.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { mnemonicGenerate } = require('@polkadot/util-crypto');
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  const mnemonic = mnemonicGenerate();
  const newAccount = await keyring.addFromUri(mnemonic);
  console.log(`Endereço: ${newAccount.address}`);
  console.log(`Mnemônico: ${mnemonic}`);
};

main().catch((err) => {console.error(err)}).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

Em uma janela de terminal, execute node create_account.js 4 (quatro) vezes para gerar os dados que precisamos. Copie/cole os mnemônicos e endereços de cada nova conta no modelo .env fornecido.

  • Alice: A conta à qual "perderemos" o acesso.

  • AliceProxy: Usado para fazer transações em nome da conta "perdida" de Alice.

  • Bob & Charlie: Essas contas representam indivíduos que atestarão nossa propriedade da conta Alice.

Obtenha algum financiamento para Alice para pagar as taxas de depósito acessando https://faucet.figment.io/ e inserindo o primeiro endereço que geramos. Como precisaremos pagar pelas transações durante o tutorial, também será necessário transferir alguns tokens para as outras contas. Isso será abordado à medida que prosseguirmos.

alice transfer process

Adicionar uma conta proxy para Alice

Crie um arquivo chamado create_proxy.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format')
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  // 1. Usa formatBalance() para deixar os valores legíveis
  formatBalance.setDefaults({
    unit: 'WND',
    decimals: 12,
  })

  // 2. Define as constantes relevantes
  const DELAY_PERIOD = 0;
  const PROXY_TYPE = 'Staking';
  const AMOUNT_TO_SEND = 5200000000000; // 5.2000 WND
  const DEPOSIT_BASE = api.consts.proxy.proxyDepositBase.toString();     // 1,000,400,000,000 = 1.00040 WND
  const DEPOSIT_FACTOR = api.consts.proxy.proxyDepositFactor.toString(); //     1,650,000,000 = 0.00165 WND
  const CHECKSUM = parseInt(DEPOSIT_BASE) + parseInt(DEPOSIT_FACTOR);    // 1,002,050,000,000 = 1.00200 WND

  // 3. Inicializa as contas
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const AliceProxy = keyring.addFromUri(process.env.PROXY_MNEMONIC);

  // 4. Envia 1 WND Para o novo proxy de stake
  const txTransferHash = await api.tx.balances
    .transfer(AliceProxy.address, AMOUNT_TO_SEND)
    .signAndSend(Alice, {tip: 10000000000});
  console.log(`Valores obrigatórios: .transfer(destination, amount)`);     
  console.log(`Valores enviados: .transfer(${AliceProxy.address}, ${formatBalance(AMOUNT_TO_SEND)})`); // 1.0000 WND
  console.log(`transfer() tx: https://westend.subscan.io/extrinsic/${txTransferHash}`); 

  // 5. Cria um novo proxy de stake
  const txAddHash = await api.tx.proxy
    .addProxy(AliceProxy.address, PROXY_TYPE, DELAY_PERIOD)
    .signAndSend(Alice, {tip: 10000000000});
  console.log(`\nproxyDepositBase \+ ( proxyDepositFactor * number of proxies )\n : ${formatBalance(DEPOSIT_BASE)} \+ ${formatBalance(DEPOSIT_FACTOR)} \= ${formatBalance(parseInt(DEPOSIT_BASE)+parseInt(DEPOSIT_FACTOR))}\n`);
  console.log(`Valores obrigatórios: .addProxy(address, type, delay)`);     
  console.log(`Valores enviados: .addProxy(${AliceProxy.address}, ${PROXY_TYPE}, ${DELAY_PERIOD})`);
  console.log(`addProxy() tx: https://westend.subscan.io/extrinsic/${txAddHash}\n`);  
}

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode
  • DELAY é o período de anúncio exigido do pedido de procuração inicial. Isso geralmente será zero.

  • PROXY_TYPE será Staking, pois os outros tipos de proxy não são suficientes para nossos propósitos. Saiba mais sobre a estrutura da conta e os vários tipos de proxy no Polkadot Wiki.

  • AMOUNT_TO_SEND é igual às 12 casas decimais que representam o valor.

  • addProxy() requer um depósito na moeda nativa (ou seja, WND ou DOT), para pagar pelo espaço de armazenamento necessário na cadeia. api.consts.proxy.proxyDepositBase é o valor base da moeda que deve ser reservado ao criar uma lista de proxy. Para cada proxy adicional adicionado à lista, um valor definido pelo api.consts.proxy.proxyDepositFactor também é reservado.

  • transfer() recebe um endereço de destino e um valor - estamos enviando WND suficiente para a conta proxy para que ela possa pagar o depósito e iniciar a tentativa de recuperação. Adicionamos uma dica ao validador ao enviar várias transações não em lote. Isso evita que um deles receba uma prioridade muito baixa para ser executado.

Execute o código com o node create_proxy.js. A saída esperada será semelhante a este exemplo:

Required values  : .transfer(destination, amount)
Submitted values : .transfer(5FsyYpFCETZpmexY3FZuD5oxK3viQwcDenHa5hiHsVyaqvYA, 2.0000 WND)
transfer() tx: https://westend.subscan.io/extrinsic/...

proxyDepositBase + proxyDepositFactor = 1.0004 WND + 1.6500 mWND = 1.0020 WND

Required values  : .addProxy(address, type, delay)
Submitted values : .addProxy(5FsyYpFCETZpmexY3FZuD5oxK3viQwcDenHa5hiHsVyaqvYA, Staking, 0)
addProxy() tx: https://westend.subscan.io/extrinsic/...
Enter fullscreen mode Exit fullscreen mode

Sobre quantidades:
Leitores atentos notarão que o fator de depósito é exibido como 1,6500 mWND - isso ocorre porque formatBalance() adiciona automaticamente um qualificador de valor e trunca a exibição para quatro casas decimais. mWND significa micro-WND com 10 casas decimais, enquanto a menor unidade de um token WND seria um pWND ou pico-WND, com 12 casas decimais.

formatBalance.setDefaults({
  unit: 'WND',
  decimals: 12,
})
Enter fullscreen mode Exit fullscreen mode

A chamada formatBalance.setDefaults() especifica o símbolo para cada unidade monetária e um número de decimais suportados. Podemos ver que fornecer AMOUNT_TO_SEND para uma função de transferência funciona bem, mas exibir esse número para os usuários ou solicitar que os usuários insiram valores com doze dígitos extras seria uma bagunça. É por isso que formatBalance() existe. Visualize as doze casas decimais assim:

// 1,000,400,000,000 = 1.00040 WND
//     1,650,000,000 = 0.00165 WND
// 1,002,050,000,000 = 1.00200 WND
// 5,000,000,000,000 = 5.00000 WND
//             1,337 = 0.0000000001337 WND (1337 pWND)
Enter fullscreen mode Exit fullscreen mode

Fundo Bob & Charlie

Crie um arquivo chamado fund_friends.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format')
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  // 1. Usa formatBalance() para deixar os valores legíveis
  formatBalance.setDefaults({
    unit: 'WND',
    decimals: 12,
  })   

  // 2. Define as constantes relevantes
  const AMOUNT_TO_SEND = 500000000000;
  const displayAmount = formatBalance(AMOUNT_TO_SEND); // 0.5000 WND

  // 3. Inicializa as contas
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const Bob = keyring.addFromUri(process.env.BOB_MNEMONIC);
  const Charlie = keyring.addFromUri(process.env.CHARLIE_MNEMONIC);

   // 4. Define um array de transações
  const transactions = [
    api.tx.balances.transfer(Bob.address, AMOUNT_TO_SEND),
    api.tx.balances.transfer(Charlie.address, AMOUNT_TO_SEND),
  ];

  // 5. Envia um lote de transações
  const txHash = await api.tx.utility
    .batch(transactions)
    .signAndSend(Alice);
  console.log(`Enviado ${displayAmount} to ${Bob.address} & ${Charlie.address}`);     
  console.log(`Valores obrigatórios : .batch([transactions])`);     
  console.log(`Valores enviados: .batch(${JSON.stringify(transactions, null, 2)})`);
  console.log(`batch() tx: https://westend.subscan.io/extrinsic/${txHash}`);
};

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

Este é um exemplo de como é simples fazer transações em lote com o PolkadotJS. Tudo o que fizemos aqui foi definir um array de transferências, que serão automaticamente processadas, assinadas e enviadas para a rede com apenas algumas chamadas de método. Vá em frente e execute o código no terminal com o node fund_friends.js. A saída será semelhante a este exemplo (alguns removidos para exibição):

Required values  : .batch([transactions])
Submitted values : .batch([
  "0xac040400004c5f5c983eaa1a5ce7cf4462b4f527f69c3b9cb284e2ae941d1b8b3a85a...",
  "0xac04040000ee43c4203c16f4f9f2577a7fb85136788c9aefd0f0666d678078d784c86..."
])
Sending 500.0000 mWND to 5DnqpngDQQ4pNpHgmGyhyzrpCaXawGHRiHRoPvdigLpHSQ8K & 
5HT7PFajmKLC7RvLHKNBicuf9xYhMH6tpUzbJDi5EMYFRhQs
batch() tx: https://westend.subscan.io/extrinsic/...
Enter fullscreen mode Exit fullscreen mode

Os valores enviados são os dados de hash para as funções de transferência que definimos na matriz de transações, que serão processadas pela função batch(). Verifique o link da SubScan, para visualizar a transação bem-sucedida.

Imagem da transação bem sucedida

Neste ponto, estamos configurados e devemos ter uma conta principal financiada com um saldo reservado de pouco mais de 1 WND, uma conta proxy em funcionamento e duas contas separadas com 0,5 WND cada. A próxima etapa é criar uma configuração de recuperação.

Criar uma configuração de recuperação

NOTA: Esta etapa deve ser concluída antes que uma frase inicial seja perdida!

Configuração de recuperação

A criação de uma configuração de recuperação no armazenamento requer o pagamento de um depósito. O valor base é fixo, com uma taxa de depósito adicional baseada no número de amigos que configuramos para serem nossos contatos de recuperação social.

Crie um arquivo chamado create_recovery.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format')
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  // 1. Usa formatBalance() para deixar os valores legíveis
  formatBalance.setDefaults({
    unit: 'WND',
    decimals: 12,
  })

  // 2. Define as constantes relevantes
  const THRESHOLD = 2;
  const DELAY_PERIOD = 0;
  const DEPOSIT_BASE = api.consts.recovery.configDepositBase.toString();     // 5,000,000,000,000 = 5.00000 WND
  const DEPOSIT_FACTOR = api.consts.recovery.friendDepositFactor.toString(); //   500,000,000,000 = 0.50000 WND

  // 3. Inicializa as contas
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const Bob = keyring.addFromUri(process.env.BOB_MNEMONIC);
  const Charlie = keyring.addFromUri(process.env.CHARLIE_MNEMONIC);
  const friends = [
    Bob.address,
    Charlie.address,
  ].sort(); 

  // 4. Cria uma configuração de recuperação
  const txHash = await api.tx.recovery
    .createRecovery(friends, THRESHOLD, DELAY_PERIOD)
    .signAndSend(Alice);
  console.log(`\nconfigDepositBase \+ ( friendDepositFactor * number of friends )\n : ${formatBalance(DEPOSIT_BASE)} \+ ${formatBalance(DEPOSIT_FACTOR * friends.length)} \= ${formatBalance(parseInt(DEPOSIT_BASE)+parseInt(DEPOSIT_FACTOR*friends.length))}\n`);
  console.log(`Valores obrigatórios: .createRecovery(friends, threshold, delayPeriod)`);     
  console.log(`Valores enviados: .createRecovery(${JSON.stringify(friends, null, 2)}, ${THRESHOLD}, ${DELAY_PERIOD})`);     
  console.log(`createRecovery tx: https://westend.subscan.io/extrinsic/${txHash}`);
};

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode
  • THRESHOLD é o número de transações de voucher individuais necessárias para que a recuperação social seja acionada.

  • DELAY_PERIOD é o número de blocos necessários para passar após o início de uma tentativa de recuperação, antes que a configuração de recuperação possa ser reivindicada.

  • DEPOSIT_BASE e DEPOSIT_FACTOR são os valores de api.consts.recovery que nos informam sobre o valor a ser definido como saldo reservado. As configurações de recuperação exigem depósitos na moeda nativa.

(ou seja, WND ou DOT) para ser criado. O depósito é necessário porque estamos adicionando dados ao espaço de armazenamento on-chain, que deve ser replicado em todos os pontos da rede.

  • friends é um array contendo os endereços de nossos contatos de recuperação social. Eles precisam ser classificados e esta matriz não pode conter nenhuma duplicata. Existe um api.consts.recovery.maxFriends que limita o número de endereços - é definido como 9.

Execute o código em um terminal com o comando node create_recovery.js :

configDepositBase + ( friendDepositFactor * number of friends ) 
 : 5.0000 WND + 1.0000 WND = 6.0000 WND
Enter fullscreen mode Exit fullscreen mode
Required values : .createRecovery(friends, threshold, delayPeriod)
Submitted values : .createRecovery([
  "5DnqpngDQQ4pNpHcmGyhyzrpCaXawGHRiHRoPvdigLpHSQ8K",
  "5HT7PFajmKLC7RvGHKNBicuf9xYhMH6tpUzbJDi5EMYFRhQs"
], 2, 0)
createRecovery tx: https://westend.subscan.io/extrinsic/...
Enter fullscreen mode Exit fullscreen mode

Esteja ciente de que podemos encontrar um erro: 1010: Transação inválida se não houver saldo suficiente na conta Alice para pagar o depósito e as taxas de rede. Precisamos de um mínimo de cerca de 6 WND de saldo disponível, que devemos ter depois de visitar a torneira durante a configuração.

No Polkadot configDepositBase é 20.008 e o friendDepositFactor é 0.033

Portanto, o valor do depósito exigido para novas configurações de recuperação social no Polkadot é igual (em DOT): 20,008 + (0,033 * num_friends)

Neste ponto, temos a opção de remover o armazenamento de recuperação para recuperar o valor do depósito com removeRecovery() ou iniciar o processo de recuperação chamando iniciateRecovery().

Iniciar a recuperação da conta proxy

Iniciar recuperação da conta proxy

Crie um arquivo chamado initial_recovery.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format')
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

   // 1. Usa formateBalance() para deixar os valores legíveis
  formatBalance.setDefaults({
    unit: 'WND',
    decimals: 12,
  })

  // 2. inicializa as contas do mnemonic
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const AliceProxy = keyring.addFromUri(process.env.PROXY_MNEMONIC);

  // 3. Inicia o processo de recuperação social
  const txHash = await api.tx.recovery
    .initiateRecovery(Alice.address)
    .signAndSend(AliceProxy);
  console.log(`Depósito de recuperação: ${formatBalance(api.consts.recovery.recoveryDeposit.toString())}`); // 5.0000 WND
  console.log(`initiateRecovery() tx: https://westend.subscan.io/extrinsic/${txHash}`);

};

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

initialRecovery() cria uma solicitação de recuperação ativa no armazenamento, que precisa ser confirmada por nossos contatos de recuperação social.

O valor api.consts.recovery.recoveryDeposit será automaticamente reservado do saldo disponível da conta AliceProxy - é por isso que transferimos 5.2 WND para o AliceProxy durante a configuração. Se o valor recoveryDeposit não estiver disponível no Proxy, esta etapa falhará. Se o closeRecovery() for chamado neste estágio, a solicitação de recuperação ativa será removida, reembolsando também o recoveryDeposit para a conta recuperável, Alice.

Depois de initiateRecovery() ter sido chamado, é possível usar closeRecovery() para encerrar prematuramente o processo de recuperação sem concluí-lo. Uma vez que closeRecovery() tenha sido chamado em todas as configurações de recuperação ativas, é possível chamar removeRecovery() - Isso excluirá a configuração de recuperação do armazenamento. Isto é útil nos casos em que for necessário alterar a lista de contatos de recuperação social, uma vez que não existe forma de atualizar a lista existente.

Execute o node initial_recovery.js :

Recovery deposit: 5.0000 WND
initialRecovery() tx: https://westend.subscan.io/extrinsic/...

A maneira de ter certeza de que foi concluído com sucesso é seguir o link para o explorador de blocos SubScan e ver se os eventos da transação que acabamos de enviar incluem uma ação de recuperação (RecoveryInitiated) bem-sucedida, que se pareceria com este exemplo:

dados do eventos da transação que acabamos de enviar:

Comprovar a recuperação

Comprovar a recuperação

Crie um arquivo chamado vouch_recovery.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format')
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  // 1. Inicializa conta(s)
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const AliceProxy = keyring.addFromUri(process.env.PROXY_MNEMONIC);
  const Bob = keyring.addFromUri(process.env.BOB_MNEMONIC);
  const Charlie = keyring.addFromUri(process.env.CHARLIE_MNEMONIC);

  // Amigo 1 atesta nosso processo de recuperação
  const txHash1 = await api.tx.recovery
    .vouchRecovery(Alice.address, AliceProxy.address)
    .signAndSend(Bob);
  console.log(`Tx da Comprovação de Bob: https://westend.subscan.io/extrinsic/${txHash1}`);

  // Amigo 2 atesta nosso processo de recuperação
  const txHash2 = await api.tx.recovery
    .vouchRecovery(Alice.address, AliceProxy.address)
    .signAndSend(Charlie);
  console.log(`Tx da Comprovação de Charlie: https://westend.subscan.io/extrinsic/${txHash2}`);
};

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

Depois que essas transações forem bem-sucedidas, a conta AliceProxy poderá reivindicar a configuração de recuperação do armazenamento, o que concede autoridade para assinar em nome de Alice.
Sem esta parte do processo, a recuperação social é impossível. Por isso é de vital importância manter um bom relacionamento com as pessoas que selecionamos para serem nossos contatos de recuperação social.

Execute o node vouch_recovery.js :

Bob vouch tx: https://westend.subscan.io/extrinsic/...
Charlie vouch tx: https://westend.subscan.io/extrinsic/...
Enter fullscreen mode Exit fullscreen mode

Em um cenário ativo envolvendo contas com valor real (DOT em vez de WND), essas funções seriam chamadas por indivíduos separados em momentos diferentes. Seria assim preferível (embora não totalmente necessário) comunicar em tempo real com os nossos contatos de recuperação social para coordenar este processo.

Reivindicar uma configuração de recuperação

Reivindicar uma configuração de recuperação

Crie um arquivo chamado Claim_recovery.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format')
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  // 1. Inicializa contas
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const AliceProxy = keyring.addFromUri(process.env.PROXY_MNEMONIC);

  // 2. reinvidica conta perdida
  const txHash = await api.tx.recovery
    .claimRecovery(Alice.address)
    .signAndSend(AliceProxy);
  console.log(`claimRecovery tx: https://westend.subscan.io/extrinsic/${txHash}`);
};

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

É importante observar que ClaimRecovery() falhará se for chamado antes do THRESHOLD das funções vouchRecovery() ter sido bem-sucedido. Devemos aguardar a confirmação de nossos contatos de recuperação social de que eles fizeram sua parte antes de prosseguir para reivindicar a configuração de recuperação.

Assim que soubermos que as transações de comprovante foram concluídas, execute node Claim_recovery.js :

ClaimRecovery tx: https://westend.subscan.io/extrinsic/...

Siga o link na saída do terminal para verificar se o AliceProxy reivindicou com sucesso a tentativa de recuperação. Estamos procurando a ação recovery(AccountRecovered) semelhante a este exemplo:

exemplo de ação de conta recuperada

Enviar transações como a conta recuperada

Enviar transações como a conta recuperada

Crie um arquivo chamado use_recovery.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format')
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  // 1. Usa formatBalance para tornar a quantidade legível
  formatBalance.setDefaults({
    unit: 'WND',
    decimals: 12,
  })

  // 2. Define as constantes relevantes
  const AMOUNT_TO_SEND = 1000000000000;
  const displayAmount = formatBalance(AMOUNT_TO_SEND); // 1.0000 WND
  const figmentFaucet = '5Fbm5fa1W9FhoCLBu8Tak7SWJHmbj4tRNyJrPifmLAq8PGp6';

  // 3. Inicializa as contas
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const AliceProxy = keyring.addFromUri(process.env.PROXY_MNEMONIC);

  // 4. Usa asRecovered para vincular 0,1 WND para nossa conta proxy perdida
  const call = await api.tx.balances.transfer(figmentFaucet, AMOUNT_TO_SEND);
  const txHash = await api.tx.recovery
    .asRecovered(Alice.address, call)
    .signAndSend(AliceProxy);
  console.log(`Valores obrigatórios: asRecovered(address, function)`);     
  console.log(`Valores enviados: asRecovered(${Alice.address}, ${JSON.stringify(call, null, 2)})`); 
  console.log(`asRecovered tx: https://westend.subscan.io/extrinsic/${txHash}`);
};

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

Após a reivindicação da configuração de recuperação, podemos enviar chamadas de função em nome de nossa conta perdida usando asRecovered(). Isso concede autoridade para um conjunto limitado de funções, que inclui transferências.
Há também uma função cancelRecovered() que revoga a capacidade de uma conta proxy registrada de usar asRecovered(), bem como uma função setRecovered(), que permite que uma conta root ignore o processo de recuperação e conceda autoridade para asRecovered() diretamente. Para os mais aventureiros, mais informações sobre essas funções podem ser encontradas nos arquivos de definição da API da Polkadot.

Execute o node use_recovery.js :

Required values  : asRecovered(address, function)
Submitted values : asRecovered(
    5CwJrhV9DaLncybk2vHbvt62SfwDfqMmPHVbo83u3iPkSDkc,
    "0xa804040000...")
asRecovered tx: https://westend.subscan.io/extrinsic/...
Enter fullscreen mode Exit fullscreen mode

Limpe com removeRecovery()

Crie um arquivo chamado remove_recovery.js e cole o seguinte código:

const { ApiPromise, Keyring } = require('@polkadot/api');
const { HttpProvider } = require('@polkadot/rpc-provider');
const { formatBalance } = require('@polkadot/util/format');
require("dotenv").config()

const main = async () => {
  const httpProvider = new HttpProvider(process.env.DATAHUB_URL);
  const api = await ApiPromise.create({ provider: httpProvider });
  const keyring = new Keyring({type: 'sr25519'});

  // 1. Usa formatBalance para tornar os valores legíveis
  formatBalance.setDefaults({
    unit: 'WND',
    decimals: 12,
  })

  // 2. Define as constantes relevantes
  const AMOUNT_TO_SEND = 12000000000000; // 12 WND
  const figmentFaucet = '5Fbm5fa1W9FhoCLBu8Tak7SWJHmbj4tRNyJrPifmLAq8PGp6';

  // 3. Inicializa as contas
  const Alice = keyring.addFromUri(process.env.ALICE_MNEMONIC);
  const AliceProxy = keyring.addFromUri(process.env.PROXY_MNEMONIC);

  // 4. Define um array de transações
  const transactions = [
    api.tx.recovery.closeRecovery(AliceProxy.address),
    api.tx.recovery.removeRecovery(),
  ];

  // 5. Fecha e remove a configuração de recuperação
  const closeHash = await api.tx.utility
    .batch(transactions)
    .signAndSend(Alice, { nonce: -1 } );
  console.log(`Valores obrigatórios: .batch([transactions])`);     
  console.log(`Valores enviados: .batch(${JSON.stringify(transactions, null, 2)})`);
  console.log(`batch() tx: https://westend.subscan.io/extrinsic/${closeHash}`);  

  // 6. reembolsa o faucet
  const txHash = await api.tx.balances
    .transfer(figmentFaucet, AMOUNT_TO_SEND)
    .signAndSend(Alice, { nonce: -1 });
  console.log(`transfer() tx: https://westend.subscan.io/extrinsic/${txHash}`);

};

main().catch((err) => { console.error(err) }).finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

Vamos limpar a configuração de recuperação chamando primeiro closeRecovery() e depois removeRecovery() . Isso reembolsará o depósito que fizemos anteriormente para Alice e, em seguida, enviará os tokens WND de volta para o Figment Faucet para que não estejamos empatando tokens desnecessariamente. Deve ser entendido que removeRecovery() só pode ser chamado depois que closeRecovery() tiver sido chamado em qualquer solicitação de recuperação ativa.
Em relação a signAndSend(Alice, { nonce: -1 }) , ao enviar várias chamadas de API assinadas pela mesma conta, devemos definir o nonce diretamente para evitar um erro sobre a prioridade da transação.

Antes de executar este código:
Verifique o saldo disponível da conta Alice no SubScan. Após o recoveryDeposit e o depósito de configuração de recuperação terem sido recuperados, deve haver aproximadamente 11-12 WND disponíveis para retornar ao faucet. Se o Saldo Reservado de Alice estiver acima de 1 WND exigido para a conta proxy, os outros depósitos não foram processados. Portanto, precisaríamos alterar AMOUNT-TO-SEND para que a transferência fosse bem-sucedida.
Só precisamos devolver o saldo disponível de nossa conta Alice quando terminarmos o tutorial. Se mais testes de recuperação social forem necessários, não prossiga com esta etapa.

Execute node remove_recovery.js :

Required values  : .batch([transactions])
Submitted values : .batch([
  "0x8c041206a806dbe17a11f61c09bff38ef9a78cdd1fde311ff8ee09ef241a95052903be66",
  "0x0c041207"
])
batch() tx: https://westend.subscan.io/extrinsic/...
transfer() tx: https://westend.subscan.io/extrinsic/...
Enter fullscreen mode Exit fullscreen mode

Os eventos para remoção bem-sucedida da configuração de recuperação e reembolso dos depósitos para a conta Alice serão semelhantes a este no SubScan:

Mostra os eventos de remoção bem-sucedida

Conclusão

Parabéns! Neste tutorial, aprendemos como configurar a recuperação social na Polkadot usando funções como createRecovery(), além de transferir as taxas de depósito associadas. Aprendemos como usar a função auxiliar formatBalance() para exibir valores legíveis. Abordamos como criar uma conta proxy do tipo Staking, bem como agrupar várias transações.

Agora temos o poder de proteger ativos importantes na Polkadot com uma camada adicional de segurança que envolve nossos amigos.

Este artigo foi criado por RoganX, e traduzido por Jhonattan Farias, você pode encontrar o artigo original aqui.

Top comments (0)