Nome: Wilson Pereira Barros Junior
Email: wbarroz@gmail.com
Ferramentas utilizadas:
- Editor NeoVim
- Execução em Node, Python, cURL e a ferramenta da referência para execução de chamadas de API e obtenção de "code snippets"
- IA ChatGPT e Gemini como auxílio em código e testes
Link do repositório:
https://github.com/wbarroz/NotusLabs
Link do post público:
https://www.linkedin.com/posts/wilson-pereira-barros_github-wbarroznotuslabs-pesquisa-dx-notus-activity-7384270335858180096-Zcy4?utm_source=share&utm_medium=member_desktop&rcm=ACoAAAQoLfYBUhP6NWZKfdPt9Ay0yNW4pNajLd4
Data de início: 26/09/2025
Data de conclusão: 15/10/2025
(*) Trilha A -- Smart Wallet, KYC, Fiat, Portfolio, History
(*) Trilha B -- Smart Wallet, Swaps, Transfer, Portfolio, History
( ) Trilha C -- Smart Wallet, Liquidity Pools, Portfolio, History
a. Registro de carteiras("Register Smart Wallet")
/api/v1/wallets/register
A execução deste endpoint resulta na criação de uma smart wallet, a partir da EOA(chave pública previamente criada), um valor inteiro de salt(default 0) e uma das opções de contratos p/ funcionalidade da smart wallet(no caso, foi usado o modelo "Light Account Factory", mais simples e adequado à experimentação); porém, para ser transacionada, a carteira necessitará de um depósito prévio, e só será "trazida" à vida no momento em que receber uma solicitação de transação(na prática uma cotação é o suficiente)
b. Lista das carteiras por projeto("Get Smart Wallets by Project")
/api/v1/wallets
A execução deste endpoint traz na resposta uma lista com as carteiras criadas dentro de um projeto(associado à API key)
c. Portfolio de uma carteira específica("Get Smart Wallet Portfolio")
/api/v1/wallets/${wallet}/portfolio
A execução deste endpoint traz na resposta o portfolio da carteira, i.e., um "saldo" das quantidades dos diferentes tokens suportados presentes na carteira
d. Cotação p/ transferência("Create Transfer")
/api/v1/crypto/transfer
A execução deste endpoint executa uma cotação para uma transferência a partir da carteira, indicando no retorno da chamada o id da cotação e sua efetividade (efetuável/não efetuável, baseado no saldo e no gas necessário para a realização); a efetivação deve ser feita com o uso do endpoint "Execução de operação do usuário"
e. Execução de operação do usuário("Execute User Operation")
/api/v1/crypto/execute-user-op
Este endpoint necessita do id de uma cotação e da sua assinatura feita com a chave privada da EOA, para execução efetiva da cotação
f. Criação de sessão de verificação padrão de identidade de cliente("Create a standard individual verification session")
/api/v1/kyc/individual-verification-sessions/standard
A execução deste endpoint dispara o processo de verificação de identidade do cliente, com a inclusão no corpo de envio dos dados do cliente, e a indicação no corpo do retorno os locais de "upload" das fotos da documentação a fornecer, após o que deve ser invocado o "Processamento da verificação de identidade de cliente", descrito a seguir.
g. Processamento da verificação padrão de identidade de cliente("Process a standard individual verification session")
/api/v1/kyc/individual-verification-sessions/standard/{session_id}/process
Este endpoint permite que se dispare o processamento dos dados do cliente para a verificação de identidade
h. Checagem do status de verificação padrão de identidade do cliente("Get a standard individual verification session result")
/api/v1/kyc/individual-verification-sessions/standard/{session_id}
Este endpoint permite que se verifique o status da verificação de identidade
i. Cotação de depósito fiduciário("Create Fiat Deposit Quote")
/api/v1/fiat/deposit/quote
Este endpoint faz a cotação para um depósito fiduciário numa smart wallet
j. Ordem de depósito fiduciário("Create Fiat Deposit Order")
/api/v1/fiat/deposit
Este endpoint efetua o depósito fiduciário numa smart wallet, baseado em cotação prévia
k. Cotação de saque fiduciário("Create Fiat Withdrawal Quote")
/api/v1/fiat/withdraw/quote
Este endpoint faz a cotação para um resgate fiduciário a partir de uma smart wallet
l. Ordem de saque fiduciário("Create Fiat Withdrawal Order")
/api/v1/fiat/withdraw
Este endpoint executa um resgate fiduciário a partir de uma smart wallet, baseado em cotação prévia
- Foi um problema momentâneo("bug resolvido"), a verificação de identidade individual(
/api/v1/kyc/individual-verification-sessions/standard) esteve inoperante por alguns dias, mas o apoio contínuo do pessoal da@APIajudou a depurar alguns erros de uso(meus), permitindo o sucesso na primeira tentativa quando da volta do serviço.
- Longe de ser um bug, mas aconteceu com alguma frequência e, especialmente no começo, atrapalhou um bocado(a minha falta de experiência também ajudou), foi a "generalidade" de algumas mensagens; por exemplo, ao usar o endpoint "Create Transfer"(
/api/v1/crypto/transfer), com valor insuficiente para concluir a operação:
{
"message": "An unexpected error occurred. Our team has been notified.",
"id": "INTERNAL_SERVER_ERROR",
"traceId": "28e7931e191c466bbf77718a923baf60"
}
- Entre 12 e 13h no dia 10 de outubro houve uma certa indisponibilidade, onde por exemplo as chamadas à função "Get Smart Wallet Portfolio"(
/api/v1/wallets/{walletAddress}/portfolio) retornavam sempre:
{
"message": "Failed to get balances. Please try again later.",
"id": "FAILED_TO_GET_BALANCES",
"traceId": "06ce5127231142edae48dfda1e78c7fc"
}
- Ainda nessa tarde(10/10), uma das moedas estavam incorretamente identificadas("Staked BRZ" — STBRZ — estava como "Brazilian Digital" — BRZ), o que foi prontamente corrigido — mas pode estar presente em outras moedas
- De uma nota de 1 a 5 para cada item, com comentários opcionais.
- A documentação foi suficiente? 4.5
A documentação está ótima, e o recurso de poder executar chamadas na referência, com os exemplos em diversos formatos(cURL, python, javascript, etc) é extremamente valioso, mas às vezes há detalhes nas chamadas efetivamente usados que não estão presentes no formulário de body, apenas no editor de JSON - As mensagens de erro ajudaram? 2
Sinceramente, às vezes as mensagens são um bocado genéricas, e não ajudam na depuração dos problemas como deveriam - O fluxo fez sentido? 3 As definições são claras, mas faz falta um FLUXOGRAMA com casos de uso que ilustrassem quais as sequencias típicas das chamadas, incluindo possíveis variações e enganos comuns
- O tempo de resposta era razoável? 5 Tanto no sucesso(o que felizmente aconteceu na maior parte do tempo 😃) quanto nos eventuais erros, a resposta da API foi rápida e não interferiu nos casos de uso
Os endpoints disponibilizados foram suficientes para o teste das funcionalidades, não foi notada uma ausência importante.
-
Descrições mais detalhadas e específicas nas mensagens de erro;
-
Na documentação, particularmente na referência, tornar compatíveis os campos disponíveis no formulário com o conteúdo do corpo da mensagem visível quando se habilita o editor de JSON;
-
Na documentação, os diferentes guias deveriam incluir o contexto de uso, com uma descrição mais detalhada dos passos, e também mais exemplos de código no repositório
-
Nomes de campos? Melhor manter
-
Design de endpoints? É funcional no estado em que está
-
Lógica de negócio? Seria beneficiado de fluxogramas com as sequências esperadas
-
Fluxo geral de uso? Idem lógica de negócio acima
-
Retornos da API? Mensagens de erro precisam ser mais detalhadas e menos genéricas
-
Consistência entre rotas? Parece bom como está(não atrapalhou, pelo menos)
- Muito estável -- tudo funcionou bem
- [*] Estável -- poucos problemas, nada crítico
- Instável -- muitos problemas ou travamentos
- Quebrada -- mal consegui testar
Explique com base na sua experiência. A experiência com o uso da API foi bem satisfatória pois, mesmo com alguns problemas no KYC e mensagens de erro restritas, todas as funcionalidades que se planejava testar foram experimentadas com sucesso.
Foi possível realizar todos os "caminhos felizes" que permitiram verificar as principais funcionalidades da plataforma, o que talvez tenha ficado de fora foi uma teste mais sistemático de todas as funcionalidades, mas isso estava fora do escopo inicial e do tempo disponível.
Para finalizar, uma seqüência com os casos de uso das trilhas 1 & 2:
-
No dashboard, um projeto é criado:
-
Para os testes, serão criadas duas carteiras("smart wallets"), a partir de um par de chaves(pública & privada, que constituem uma EOA) que pode ser obtido pelo seguinte comando do Foundry SDK:
cast wallet new -
Com as chaves acima obtidas, já se torna possível criar as carteiras, através do código
https://github.com/wbarroz/NotusLabs/tree/main/notus-cli, registrando-as com o seguinte corpo de mensagem:{ "factory": "0x0000000000400CdFef5E2714E63d8040b700BC24", "externallyOwnedAccount": "0xfa..9c", "salt": "0" }com a chamada:
npm run register -- reg_wallet.json # usada a função "Register Smart Wallet"(/api/v1/wallets/register)sendo que para a primeira carteira o campo "salt" fica a "0" como mostrado acima e para a segunda o valor é "1", e "factory" traz o tipo de smart contract atrelado às accounts(o que caracteriza a "smart wallet") usado, que no nosso caso é o mais simples — "Light Account Factory"; as carteiras ficam como a seguir:
-
Para exercitar as transferências de valores entre as carteiras, é necessário um depósito inicial, o que vai ser feito através da rampa de entrada(on-ramp); para tanto, é necessária a habilitação da rampa para o projeto criado(procedimento interno), e a criação de uma identificação, através do processo de KYC para o usuário, que consiste na verificação de documentação e prova de vida(aqui não usado para efeito de simplicidade, mas que pode ser feito): o KYC é iniciado através da chamada da função "Create a standard individual verification session", que pode ser executada no código
https://github.com/wbarroz/NotusLabs/tree/main/kyc/kyc_py, usando o seguinte corpo de mensagem:{ "firstName": "Joao", "lastName": "da Silva Souza", "birthDate": "20/04/1993", "documentCategory": "IDENTITY_CARD", "documentCountry": "BRAZIL", "documentId": "13333333332", "livenessRequired": false, "email": "exemplo@email.com.br", "address": "Rua Generica, 7", "city": "Campinas", "state": "SP", "postalCode": "09999990", "nationality": "BRAZILIAN" }...e a seguinte chamada:
./kyc.py --body form.json --front frente.jpg --back verso.jpg
O processo de KYC envolve o envio da mensagem acima, seguido pelo envio(em caso de um início de verificação bem-sucedido) da(s) foto(s) de documento, seguido pela consulta do status do processo em que a resposta pode ser "PENDING"(fotos não enviadas), "PROCESSING(fotos enviadas, fazendo processamento)" , "VERIFYING"(fazendo a verificação das informações) , "COMPLETED"(verificação bem-sucedida, inclue o individualId) , "FAILED"(falhou verificação) ou "EXPIRED(não enviadas a(s) foto(s) de documento no tempo hábil". Todo esse processo é realizado pelo código acima mencionado. Convém mencionar que o procedimento de envio das fotos poderia se beneficiar de uma descrição, ainda que sucinta, do processo de upload no AWS S3 usado(no caso o assistente de IA foi capaz de criar a automação necessária, baseado nos campos de retorno da mensagem inicial — "Create a standard individual verification session"). -
Obtido o "individualId" num projeto habilitado ao uso da rampa, podem ser feitas as transações com vista à conversão de moeda fiduciária em crypto-ativos; para tanto, o primeiro passo é a execução de uma cotação do depósito em dinheiro para uma das carteiras, o que é feito através do endpoint "Create Fiat Deposit Quote", usando-se o seguinte conteúdo(por exemplo)no corpo da mensagem:
{ "paymentMethodToSend": "PIX", "receiveCryptoCurrency": "BRZ", "amountToSendInFiatCurrency": 27.55, "individualId": "ff..8d", "walletAddress": "0x57..1c", "chainId": 137 }como pode ser visto, o criptoativo alvo para o depósito é BRZ(para essa operação, podem ser usados BRZ — "Brazilian Digital" — e USDC — "USD Coin"); na resposta à esta requisição, se viável(valor mínimo em reais: R$ 0,01, endereço correto de carteira, usuário, etc), são confirmados os valores, incluindo a efetiva conversão(no caso, 1:1) e sua validade:
{ "depositQuote": { "quoteId": "be885ff6-52e6-467f-b32b-7ac6bcdd5a2f", "amountToSendInFiatCurrency": "27.55", "amountToReceiveInCryptoCurrency": "27.55", "expiresAt": "2025-10-13T20:12:18.382Z" } }Tudo o mais correto, a ordem tem sua efetivação iniciada através do endpoint "Create Fiat Deposit Order", usando o seguinte corpo de mensagem:
{ "quoteId": "be885ff6-52e6-467f-b32b-7ac6bcdd5a2f", "walletAddress": "0x57..1c" }Na resposta à esta última requisição, estarão presentes as informações para o depósito via PIX:
{ "depositOrder": { "orderId": "925c869f-27ca-406b-b872-db6c5930c106", "expiresAt": "2025-10-13T20:12:18.382Z", "paymentMethodToSendDetails": { "type": "PIX", "pixKey": "000...br.gov.bcb.pix...pix.b...com/qrs1/v2/01djWpcPZxXuRjHepRUw1gh352gVkSWgRPuXzFdgxX5MXNNay520400005303986540527.555802BR59213rz .....................Rio de Janeiro6***************D26", "base64QrCode": "iVBORw0KGgoAAAANXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX5CYII=" } } }Usando-se o código em
https://github.com/wbarroz/NotusLabs/blob/main/notus-cli/notus-cli.js, com o seguinte comando:npm run deposit -- deposit_body.json executee tendo no arquivo
deposit_body.jsono conteúdo do corpo de mensagem inicial acima mostrado, toda essa sequência de operação é executada automaticamente, com a geração de um arquivo PNG com o QR-Code para a efetuação do depósito via PIX. -
Através do endpoint "Get Smart Wallet Portfolio", é possível verificar, no corpo da mensagem de retorno, a carteira destino com os recursos recém-depositados:
{ "tokens": [ { "chainId": 137, "balance": "27550000000000000000", "priceUsd": "0.1817383484", "balanceUsd": "5.00689149842", "balanceFormatted": "27.55", "address": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "name": "Brazilian Digital", "symbol": "brz", "logo": "https://coin-images.coingecko.com/coins/images/8472/large/MicrosoftTeams-image_%286%29.png?1696508657", "decimals": 18, "chain": { "id": 137, "logo": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745", "name": "Polygon", "symbol": "POL" } } ], "nfts": [], "portfolio": [ { "chainId": 137, "balance": "27550000000000000000", "priceUsd": "0.1817383484", "balanceUsd": "5.00689149842", "balanceFormatted": "27.55", "address": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "name": "Brazilian Digital", "symbol": "brz", "logo": "https://coin-images.coingecko.com/coins/images/8472/large/MicrosoftTeams-image_%286%29.png?1696508657", "decimals": 18, "chain": { "id": 137, "logo": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745", "name": "Polygon", "symbol": "POL" } } ] } -
Uma vez havendo saldo numa carteira, pode-se fazer operações de transferência e/ou swap, sendo que essa última operação(endpoint "Create Swap" — /api/v1/crypto/swap) permite que se faça também a transferência na mesma funcionalidade; por exemplo, através do comando:
npm run swap -- swap_body.json executee usando o seguinte conteúdo no arquivo
swap_body.json:{ "amountIn": "15.00", "chainIdIn": 137, "chainIdOut": 1, "gasFeePaymentMethod": "DEDUCT_FROM_AMOUNT", "payGasFeeToken": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "tokenIn": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "tokenOut": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "walletAddress": "0x57..1c", "toAddress": "0xc5..4a", "routeProfile": "BEST_OUTPUT", "transactionFeePercent": null, "slippage": 5 }será executado:
- "Create Swap", usando o conteúdo acima, o que implica:
- Uma quantia de entrada de 15.00, na token de entrada(BRZ — 0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc) na rede de entrada(137 — Polygon); essa situação foi definida ainda no depósito via PIX;
- A chain de saída é Ethereum(1), tendo como token de saída Shiba Inu(0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce)
- A carteira de onde sai o recurso é "0x57..1c"(criada com "salt" zero), e a carteira a receber é "0xc5..4a"(criada com "salt" 1)
- O valor indicado servirá para a transferência e cobertura de qualquer custo da transação, dada a opção "DEDUCT_FROM_AMOUNT"(a alternativa seria "ADD_TO_AMOUNT", o que implica "amountIn" corresponder ao valor da transferência e toda taxa ser cobrada à parte)
- Não é estipulado uma porcentagem a remunerar o "tesouro"(uma carteira definida para receber taxas oriundas das transferências), dada a simplicidade da demonstração("transactionFeePercent")
- A tolerância entre o valor nominal("amountIn") e o efetivamente executado, no caso da presente solicitação, é de 5%("slippage")
- A resposta ao comando "Create Swap" descrito acima será uma sequência de cotações, cada uma na forma:
{ "amountIn": "15.00", "amountInUSD": "2.7240819056718136665192", "amountOutUSD": "2.2687587677997714", "chainIn": 137, "chainOut": 1, "estimatedExecutionTime": "2025-10-14T00:57:18.041Z", "estimatedCollectedFee": { "collectedFee": "0", "collectedFeeToken": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "collectedFeePercent": "0", "notusCollectedFee": "0.03", "notusCollectedFeePercent": "0.2" }, "estimatedGasFees": { "payGasFeeToken": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "maxGasFeeToken": "0.01934719714136787", "gasFeeTokenAmount": "0.01934719714136787", "gasFeeTokenAmountUSD": "0.0035148082855095203772170390169945", "maxGasFeeNative": "0.037931512746807708" }, "expiresAt": 1760403439000, "minAmountOut": "193591.231615782554529124", "quoteId": "0x78cf1aec46dbefcddb746ef42e77c2b504752c8571d8b2606802fd71669507e6", "userOperationHash": "0x78cf1aec46dbefcddb746ef42e77c2b504752c8571d8b2606802fd71669507e6", "revertReason": null, "authorization": null, "swapProvider": "RANGO", "tokenIn": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "tokenInPrice": "0.18184", "tokenOut": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "walletAddress": "0x57..1c", "metadata": null }Escolhida a cotação(no caso do comando usado, será sempre a primeira cotação retornada), usa-se o endpoint "Execute User Operation" para a execução do "quoteId" correspondente. Concluída a operação, pode ser verificado o saldo resultante na carteira destino(através do endpoint "Get Smart Wallet Portfolio"):
{ "tokens": [ { "chainId": 1, "balance": "205706273389756124737807", "priceUsd": "0.0000111084", "balanceUsd": "2.2850675673227669360374552788", "balanceFormatted": "205706.273389756124737807", "address": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "name": "Shiba Inu", "symbol": "shib", "logo": "https://coin-images.coingecko.com/coins/images/11939/large/shiba.png?1696511800", "decimals": 18, "chain": { "id": 1, "logo": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "name": "Ethereum", "symbol": "ETH" } } ], "nfts": [], "portfolio": [ { "chainId": 1, "balance": "205706273389756124737807", "priceUsd": "0.0000111084", "balanceUsd": "2.2850675673227669360374552788", "balanceFormatted": "205706.273389756124737807", "address": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "name": "Shiba Inu", "symbol": "shib", "logo": "https://coin-images.coingecko.com/coins/images/11939/large/shiba.png?1696511800", "decimals": 18, "chain": { "id": 1, "logo": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "name": "Ethereum", "symbol": "ETH" } } ] } - "Create Swap", usando o conteúdo acima, o que implica:
-
Na próxima operação, uma transferência simples, o restante do recurso na carteira origem(0x57..1c), em BRZ também será enviado para a carteira "0xc5..4a"; para realizar a transferência, o endpoint "Transfer"(/api/v1 /crypto/transfer), é usado, através da seguinte chamada:
node notus-cli.js transfer transfer_body.json executeusando como corpo da mensagem(conteúdo do arquivo "transfer_body.json") o seguinte:
{ "amount": "12.55", "chainId": 137, "gasFeePaymentMethod": "DEDUCT_FROM_AMOUNT", "payGasFeeToken": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "token": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "walletAddress": "0x57..1c", "toAddress": "0xc5..4a", "transactionFeePercent": null }será executado:
- "Create Transfer", usando o conteúdo acima, o que implica:
- A quantia de 12.55, na token de entrada(BRZ — 0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc) na rede de entrada(137 — Polygon); servirá para a transferência e custos associados("DEDUCT_FROM_AMOUNT");
- Por ser uma transferência, tanto o token(BRZ) quanto a chain de destino(Polygon) são os mesmos;
- A carteira de onde sai o recurso é "0x57..1c" e a carteira a receber é "0xc5..4a"(tal como no exemplo anterior)
- Não é estipulado uma porcentagem a remunerar o "tesouro"(tal como na operação de swap anterior)
- A resposta ao comando "Create Transfer", quando bem sucedido, será como a seguir:
{ "transfer": { "amountToBeReceived": "12.538517674136121511", "amountToBeReceivedUSD": "2.27420180981695923500438952026790157", "amountToSend": "12.55", "amountToSendUSD": "2.2762844424645492685", "chain": 137, "estimatedExecutionTime": "2025-10-14T12:26:04.881Z", "estimatedGasFees": { "gasFeeTokenAmount": "0.011482325863878489", "gasFeeTokenAmountUSD": "0.00208263264759003349561047973209843", "maxGasFeeNative": "0.009858853649052191", "maxGasFeeToken": "0.011482325863878489", "payGasFeeToken": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc" }, "estimatedCollectedFee": { "collectedFee": "0", "collectedFeeToken": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "collectedFeePercent": "0", "notusCollectedFee": "0", "notusCollectedFeePercent": "0" }, "expiresAt": 1760444810000, "quoteId": "0x05278e974139d89ac749473f6a2f4a734f9643b00d56cbac3cf7311634c21e36", "userOperationHash": "0x05278e974139d89ac749473f6a2f4a734f9643b00d56cbac3cf7311634c21e36", "revertReason": null, "authorization": null, "toAddress": "0xc5..4a", "walletAddress": "0x57..1c", "token": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "metadata": null } }Aqui veem-se o valor efetivamente transferido("amountToBeReceived"), as "fees" recolhidas, tanto no token usado mas também em USD, a validade da cotação, entre outros; a seguir, procede-se à execução da transferência via "Execute User Operation", usando-se a informação da cotação; a execução do comando acima descrito executa automaticamente toda essa sequência. Tendo sido feita com sucesso, a transferência pode ser verificada no portfólio da carteira destino(através do endpoint "Get Smart Wallet Portfolio"), agora indicando a presença de ambos os tokens:
{ "tokens": [ { "chainId": 137, "balance": "12538517674136121511", "priceUsd": "0.1806644495", "balanceUsd": "2.2652643931438227808499231945", "balanceFormatted": "12.538517674136121511", "address": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "name": "Brazilian Digital", "symbol": "brz", "logo": "https://coin-images.coingecko.com/coins/images/8472/large/MicrosoftTeams-image_%286%29.png?1696508657", "decimals": 18, "chain": { "id": 137, "logo": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745", "name": "Polygon", "symbol": "POL" } }, { "chainId": 1, "balance": "205706273389756124737807", "priceUsd": "0.000010308", "balanceUsd": "2.120420266101606133797314556", "balanceFormatted": "205706.273389756124737807", "address": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "name": "Shiba Inu", "symbol": "shib", "logo": "https://coin-images.coingecko.com/coins/images/11939/large/shiba.png?1696511800", "decimals": 18, "chain": { "id": 1, "logo": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "name": "Ethereum", "symbol": "ETH" } } ], "nfts": [], "portfolio": [ { "chainId": 137, "balance": "12538517674136121511", "priceUsd": "0.1806644495", "balanceUsd": "2.2652643931438227808499231945", "balanceFormatted": "12.538517674136121511", "address": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "name": "Brazilian Digital", "symbol": "brz", "logo": "https://coin-images.coingecko.com/coins/images/8472/large/MicrosoftTeams-image_%286%29.png?1696508657", "decimals": 18, "chain": { "id": 137, "logo": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745", "name": "Polygon", "symbol": "POL" } }, { "chainId": 1, "balance": "205706273389756124737807", "priceUsd": "0.000010308", "balanceUsd": "2.120420266101606133797314556", "balanceFormatted": "205706.273389756124737807", "address": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "name": "Shiba Inu", "symbol": "shib", "logo": "https://coin-images.coingecko.com/coins/images/11939/large/shiba.png?1696511800", "decimals": 18, "chain": { "id": 1, "logo": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1696501628", "name": "Ethereum", "symbol": "ETH" } } ] } - "Create Transfer", usando o conteúdo acima, o que implica:
-
Como penúltimo passo, vamos converter na carteira destino o montante em Shiba Inu para BRZ, usando:
npm run swap -- swap_body.json executetendo no arquivo "swap_body.json" o seguinte:
{ "amountIn": "205706.273389756124737807", "chainIdIn": 1, "chainIdOut": 137, "gasFeePaymentMethod": "DEDUCT_FROM_AMOUNT", "payGasFeeToken": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "tokenIn": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", "tokenOut": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "walletAddress": "0xc5..4a", "toAddress": "0xc5..4a", "routeProfile": "BEST_OUTPUT", "transactionFeePercent": null, "slippage": 5 }Uma nova consulta ao portfólio o mostra unificado em BRZ:
{ "tokens": [ { "chainId": 137, "balance": "16973291947706598909", "priceUsd": "0.1807678128", "balanceUsd": "3.0682248614027738609067962352", "balanceFormatted": "16.973291947706598909", "address": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "name": "Brazilian Digital", "symbol": "brz", "logo": "https://coin-images.coingecko.com/coins/images/8472/large/MicrosoftTeams-image_%286%29.png?1696508657", "decimals": 18, "chain": { "id": 137, "logo": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745", "name": "Polygon", "symbol": "POL" } } ], "nfts": [], "portfolio": [ { "chainId": 137, "balance": "16973291947706598909", "priceUsd": "0.1807678128", "balanceUsd": "3.0682248614027738609067962352", "balanceFormatted": "16.973291947706598909", "address": "0x4ed141110f6eeeaba9a1df36d8c26f684d2475dc", "name": "Brazilian Digital", "symbol": "brz", "logo": "https://coin-images.coingecko.com/coins/images/8472/large/MicrosoftTeams-image_%286%29.png?1696508657", "decimals": 18, "chain": { "id": 137, "logo": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745", "name": "Polygon", "symbol": "POL" } } ] } -
Como último passo, é feita o "off-ramping", ou seja, o saque fiduciário do valor total, usando o endpoint "Create Fiat Withdrawal Quote/Order", através do comando:
npm run withdraw -- withdraw_body.json executetendo no arquivo "swap_body.json" o seguinte:
{ "individualId": "ffbdb44e-929d-4262-b2e6-3de0849fba8d", "chainId": 137, "paymentMethodToReceiveDetails": { "type": "PIX", "pixKey": "+5511960277847" }, "amountToSendInCryptoCurrency": "16.973291947706598909", "cryptoCurrencyToSend": "BRZ", "transactionFeePercent": null, "walletAddress": "0xc5..4a" }Tendo sido a transação bem-sucedida, temos a seguinte resposta:
{ "withdrawOrder": { "userOperationHash": "0x5419cf8dd248e0f2554d0e5d93bf01e4354a80c98fefbb39ff6a09a19e4d1f52", "userOpHash": "0x5419cf8dd248e0f2554d0e5d93bf01e4354a80c98fefbb39ff6a09a19e4d1f52", "authorization": null, "orderId": "f7a8d267-2b0d-4a5a-badd-056656a4bbd3", "amountToSendInCryptoCurrency": "16.973291947706598909", "amountToReceiveInFiatCurrency": "16.93", "transactionFeeAmountInCryptoCurrency": "0", "estimatedGasFeeAmountInCryptoCurrency": "0.043291947706598909", "expiresAt": "2025-10-14T14:33:27.496Z" } }E ao executar a ordem, temos o efeito pretendido:
Essa foi uma oportunidade única em que podemos utilizar uma tecnologia que permite realizar operações WEB3 sofisticadas sem o uso de smart contracts, com um alto nível de abstração e envolvendo transações on & off ramping, tudo de forma MUITO FÁCIL 😃 !!!



