Skip to content

Commit

Permalink
Atualiza a documentação, adiciona exemplo e ajusta o docker-compose.
Browse files Browse the repository at this point in the history
  • Loading branch information
aldenio committed Apr 17, 2024
1 parent 4d9b72f commit 4324756
Show file tree
Hide file tree
Showing 5 changed files with 386 additions and 4 deletions.
1 change: 1 addition & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ services:
networks:
- starlight
container_name: timber
entrypoint: "sleep 20 && npm start"
image: timber
depends_on:
- timber-mongo
Expand Down
3 changes: 3 additions & 0 deletions exemplos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ Operação 1052: Registro de operação de compra e venda entre um participante
[Exemplo 12](example12.ts):
Operação 1052: Registro de operação de compra e venda entre dois clientes de participantes distintos.

[Exemplo 13](walletsCheckingFlow.ts):
TPFt: Verificar se a carteira está com as permissões necessárias para realizar as operações envolvendo TPFt.

[<<< Voltar](../README.md)
272 changes: 272 additions & 0 deletions exemplos/walletsCheckingFlow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
import { ethers } from "hardhat";

interface CheckAddress {
name: string;
publicAddress: string;
}

/**
* Script WalletsCheckingFlow
* Objetivo: verificar se uma ou mais carteiras estão com as permissões necessárias para realizar as operações envolvendo TPFt.
* Premissa: para executar esse script é necessário assinar a transação com uma carteira de um participante habilitado no real digital.
* @param wallets Lista de carteiras que serão verificadas
*/
async function TPFtCheckApproves(wallets: CheckAddress[]) {
// Valida se lista de carteira está vazia
if (!wallets?.length) {
throw new Error("Insira carteira(s) e os contratos de TPFt e TPFtDvP");
}
// Endereço do contrato TPFt
const TPFT_CONTRACT_ADDRESS = (await addressDiscoveryContract("TPFt"))
.contractAddress;
// Endereço do contrato TPFtDvP
const TPFT_DVP_ADDRESS = (await addressDiscoveryContract("TPFtDvP"))
.contractAddress;
// Obtém contrato TPFt
const tpftContract = await ethers.getContractAt(
"TPFt",
TPFT_CONTRACT_ADDRESS
);

console.log(`\nConsultando contrato > \x1b[33mTPFt...\x1b[0m`);
// Loop de verificação
for await (const wallet of wallets) {
// Verifica se a carteira deu aprovação para o contrato TPFtDvP operar no contrato de TPFt
const hasApprove = await tpftContract.isApprovedForAll(
wallet.publicAddress,
TPFT_DVP_ADDRESS
);
// Verifica se a carteira está habilitada no TPFt
const isEnabledAddress = await tpftContract.isEnabledAddress(
wallet.publicAddress
);
// Indica se a carteira deu aprovação ou não ao TPFtDvP
if (hasApprove) {
console.log(`>>>\x1b[32m ${wallet.name} deu aprovação ao TPFtDvP\x1b[0m`);
} else {
console.log(
`\x1b[31m ${wallet.name} não deu aprovação ao TPFtDvP\x1b[0m`
);
}
// Indica se a carteira está habilitada no contrato TPFt
if (isEnabledAddress) {
console.log(`>>>\x1b[32m ${wallet.name} está habilitado no TPFt\x1b[0m`);
} else {
console.log(`\x1b[31m${wallet.name} não está habilitado no TPFt\x1b[0m`);
}
}

console.log("---Verificação no TPFt finalizada---\n");
}
/**
* Verifica se a carteira está habilitada no Real Digital
* @param wallets Lista de carteiras que serão verificadas
*/
async function RealDigitalCheck(wallets: CheckAddress[]) {
// Valida se lista de carteira está vazia
if (!wallets?.length) {
throw new Error("Insira as carteira(s) para verificação no Real Digital");
}
// Endereço do contrato Real Digital
const REAL_DIGITAL_ADDRESS = (await addressDiscoveryContract("RealDigital"))
.contractAddress;
// Obtém contrato RealDigital
const realDigitalContract = await ethers.getContractAt(
"RealDigital",
REAL_DIGITAL_ADDRESS
);

console.log("Consultando contrato > \x1b[33mReal Digital....\x1b[0m");
// Loop de verificação
for (const wallet of wallets) {
// Verifica se a carteira está habilitada no RealDigital
const isEnable = await realDigitalContract.authorizedAccounts(
wallet.publicAddress
);
// Indica se a carteira está habilitada ou não no RealDigital
if (isEnable) {
console.log(
`>>>\x1b[32m ${wallet.name} está habilitada no Real Digital \x1b[0m`
);
} else {
console.log(
`\x1b[31m ${wallet.name} não está habilitada no Real Digital\x1b[0m`
);
}
}

console.log("---Verificação no Real Digital finalizada--\n");
}
/**
* Verifica se uma ou mais carteiras estão habilitadas no Real Tokenizado
* @param wallets Lista de carteiras que serão verificadas
* @param realTokenizados Lista de Real Tokenizado
*/
async function RealTokenizadoCheck(
wallets: CheckAddress[],
realTokenizados: CheckAddress[]
) {
// Valida se lista de carteiras ou realTokenizados estão vazias
if (!wallets?.length || !realTokenizados?.length) {
throw new Error("Insira as carteira(s) e os contrato(s) de Real Tokenizado");
}

console.log("Consultando contrato > \x1b[33mReal Tokenizado...\x1b[0m");
// Loop de verificacão
for (const realTokenizado of realTokenizados) {
// Obtém contrato do RealTokenizado
const realTokenizadoContract = await ethers.getContractAt(
"RealTokenizado",
realTokenizado.publicAddress
);
for (const wallet of wallets) {
// Verifica se a carteira está habilitada
const isEnable = await realTokenizadoContract.authorizedAccounts(
wallet.publicAddress
);
// Indica se a carteira está habilitada ou não no RealTokenizado
if (isEnable) {
console.log(
`>>>\x1b[32m ${wallet.name} está habilitada no Real Tokenizado \x1b[0m`
);
} else {
console.log(
`\x1b[31m${wallet.name} não está habilitada no Real Tokenizado \x1b[0m`
);
}
}
}

console.log("---Verificação no Real Tokenizado finalizada---\n");
}
/**
* Verifica se uma ou mais carteiras estão cadastradas no Key Dictionary
* @param wallets Lista de carteiras que serão verificadas
*/
async function keyDictionaryCheck(wallets: CheckAddress[]) {
// Endereço do KeyDictionary
const KEY_DICTIONARY_ADDRESS = (
await addressDiscoveryContract("KeyDictionary")
).contractAddress;
// Obtém contrato KeyDictionary
const keyDictionaryContract = await ethers.getContractAt(
"KeyDictionary",
KEY_DICTIONARY_ADDRESS
);
// Valor default do tipo bytes32 na DLT
const bytes32Default =
"0x0000000000000000000000000000000000000000000000000000000000000000";

console.log("Consultando contrato >\x1b[33m keyDictionary\x1b[0m");
// Loop de verificação
for await (const wallet of wallets) {
// Obtém a chave da informação do cliente
const getKey = await keyDictionaryContract.getKey(wallet.publicAddress);
// Verifica se a chave tem o valor default e faz log se a carteira está cadastrada no KeyDictionary
if (bytes32Default === getKey) {
console.log(
`\x1b[31m Carteira não está cadastrada no Key Dictionary \x1b[0m`
);
} else {
console.log(
`>>>\x1b[32m Carteira está cadastrada no Key Dictionary \x1b[0m`
);
}
// Obtém dados do cliente no contrato KeyDictionary
const clientCustomData = await keyDictionaryContract.getCustomerData(
getKey
);
// Nome do RealTokenizado
const realTokenizadoName = `RealTokenizado@${clientCustomData.cnpj8}`;
// Obtém contrato RealTokenizado
const realTokenizadoAddress = (
await addressDiscoveryContract(realTokenizadoName)
).contractAddress;
// Informação do RealTokenizado
const realTokenizado = {
name: realTokenizadoName,
publicAddress: realTokenizadoAddress,
};

console.log("---Verificação no Key Dictionary finalizada---\n");
// Chama o script do RealTokenizado para verificar se a carteira está habilitada
await RealTokenizadoCheck(wallets, [realTokenizado]);
}
}
/**
* Busca endereço do contrato no addressDiscovery
* @param key Nome do contrato
* @returns Retorna o endereço de contrato
*/
async function addressDiscoveryContract(key: string) {
// Obtém o contrato AddressDiscovery
const addressDiscoveryContract = await ethers.getContractAt(
"AddressDiscovery",
ADDRESS_DISCOVERY_ADDRESS
);
// Endereço do contrato
const contractAddress = await addressDiscoveryContract.addressDiscovery(
ethers.utils.id(key)
);
// Retorna erro se o contrato pesquisado no AddressDiscovery não existir
if (contractAddress === ethers.constants.AddressZero) {
throw new Error("Endereço de contrato não encontrado no Address Discovery");
}
// Retorna o endereço do contrato
return {
contractAddress,
};
}
/**
* Verifica se os endereços das carteiras são validos
* @param wallets Lista de carteiras que serão verificadas
*/
async function isWallets(wallets: CheckAddress[]) {
// Loop de verificação
wallets.forEach((wallet) => {
// Verifica se o endereço da carteira é valido
if (!ethers.utils.isAddress(wallet.publicAddress)) {
throw new Error(`${wallet.name} não é um endereço de carteira valido.`);
}
});
}
/**
* Executa todas as verificações
* @param wallets Lista de carteiras que serão verificadas
* @param addressDiscoveryAddress Endereço do contrato AddressDiscovery
*/
async function main(wallets: CheckAddress[], addressDiscoveryAddress: string) {
ADDRESS_DISCOVERY_ADDRESS = addressDiscoveryAddress;
isWallets(wallets);
await TPFtCheckApproves(wallets);
await RealDigitalCheck(wallets);
await keyDictionaryCheck(wallets);
}
/**
* Mapeamento de mensagens de erros
*/
const errors: Record<string, string> = {
"RealDigitalDefaultAccount: Not authorized Account":
"Signer isn't an authorized participant",
};
/**
* Endereço do contrato AddressDiscovery
*/
let ADDRESS_DISCOVERY_ADDRESS:string;
/**
* Lista de carteiras que serão verificadas
*/
const wallets: CheckAddress[] = [
{
name: "NOME_DA_CARTEIRA",
publicAddress: "ENDEREÇO_DA_CARTEIRA",
}
];
/**
* Executa todas as verificações
*/
main(wallets, "ENDEREÇO_DO_ADDRESS_DISCOVERY").catch((error) => {
const reason = error?.reason ? errors[error?.reason] : error;
console.error(`>>> \x1b[31m${reason} \x1b[0m`);
error.exitCode = 1;
});
90 changes: 90 additions & 0 deletions habilitacoes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
## Habilitações

Para executar as operações envolvendo Títulos Públicos Federais tokenizados (TPFt), é necessário que os participantes efetuem as seguintes habilitações para o contrato TPFtDvP realizar transações com os ativos de sua carteira:

- <span style="text-decoration: underline;">TPFt</span>: deve ser autorizada na carteira do participante ou cliente a manipulação do saldo de TPFt através do método `setApprovalForAll`, herdado do padrão ERC-1155, do contrato TPFt;

- <span style="text-decoration: underline;">RealDigital</span>: deve ser autorizada na carteira do participante uma quantia através do método `approve`, herdado do padrão ERC-20, do contrato RealDigital. Essa quantia poderá ser utilizada em mais de uma operação e é possível autorizar novos valores sempre que necessário; e

- <span style="text-decoration: underline;">RealTokenizado</span>: deve ser autorizada na carteira do participante e do seu cliente uma quantia através do método `approve`, herdado do padrão ERC-20, do contrato RealTokenizado. Essa quantia poderá ser utilizada em mais de uma operação e é possível autorizar novos valores sempre que necessário;

<span style="text-decoration: underline;">Além disso, ao criar novas carteiras na rede, o participante deve informar ao Bacen para que a carteira seja autorizada a ter TPFt.</span>

O detalhamento das habilitações por operação está representado no quadro abaixo:

<table>
<tr style="font-weight:bold;">
<th colspan="7" style="text-align:center;">Habilitações necessárias para operações envolvendo TPFt</th>
</tr>
<tr>
<th rowspan="2" style="text-align:left;">OPERAÇÃO TPFt</th>
<th colspan="2" style="text-align:center;">realDigital</th>
<th colspan="2" style="text-align:center;">tpfT</th>
<th colspan="2" style="text-align:center;">realTokenizado</th>
</tr>
<tr>
<th style="text-align:center;">enableAccount</th>
<th style="text-align:center;">approve</th>
<th style="text-align:center;">enableAddress</th>
<th style="text-align:center;">setApprovalForAll</th>
<th style="text-align:center;">/:enderecoContrato/enableAccount</th>
<th style="text-align:center;">/:enderecoContrato/approve</th>
</tr>
<tr>
<td>TPFtOperation1001</td>
<td></td>
<td></td>
<td style="text-align:center;">X*</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>TPFtOperation1002</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X*</td>
<td style="text-align:center;">X</td>
<td></td>
<td></td>
</tr>
<tr>
<td>TPFtOperation1070</td>
<td></td>
<td></td>
<td style="text-align:center;">X*</td>
<td style="text-align:center;">X</td>
<td></td>
<td></td>
</tr>
<tr>
<td>TPFtOperation1052 (Participante)</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X*</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X</td>
</tr>
<tr>
<td>TPFtOperation1052 (Cliente)</td>
<td></td>
<td></td>
<td style="text-align:center;">X*</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X</td>
<td style="text-align:center;">X</td>
</tr>
</table>


| **DESCRIÇÃO** |
|----------------------------------------------|
| **realDigital/enableAccount:** habilitar a carteira para operar Real Digital. |
| **realDigital/approve:** habilitar o contrato TPFtDvP a realizar transações com Real Digital pela carteira. |
| **tpft/enableAddress:** habilitar a carteira para operar TPFt. _*Somente o Bacen pode habilitar e o participante deve solicitar via e-mail._ |
| **tpft/setApprovalForAll:** habilitar o contrato TPFtDvP a realizar transações com TPFt pela carteira. |
| **realTokenizado/:enderecoContrato/enableAccount:** habilitar a carteira para operar Real Tokenizado. |
| **realTokenizado/:enderecoContrato/approve:** habilitar o contrato TPFtDvP a realizar transações com Real Tokenizado pela carteira. |

[<<< Voltar](smartcontractsTitulos.md)
Loading

0 comments on commit 4324756

Please sign in to comment.