Pular para o conteúdo principal

Enviando autorizações de carteira

Esta página é uma referência opcional de implementação com exemplos em ethers. Para consultar o ciclo completo dos pagamentos multidestino, use o guia consolidado de Pagamentos multidestino.

Ao configurar pela API a carteira multidestino de um negócio ou parceiro, a Bitpayway salva a configuração desejada e retorna uma autorização. Sua aplicação deve enviar essa autorização ao registro de carteiras na blockchain do token; uma chamada de API sozinha não gasta gas nem envia uma transação blockchain.

Para a carteira multidestino do cliente em um determinado token, o painel de negócios da Bitpayway já executa o fluxo completo: salva a carteira, obtém a autorização e envia a transação depois que o usuário a aprova na carteira conectada do navegador. Use os exemplos abaixo ao integrar diretamente com a API, operar um relayer ou criar sua própria interface. As carteiras dos parceiros sempre usam esse fluxo de API porque não podem ser alteradas no painel da Bitpayway.

A resposta é autossuficiente. Ela traz a rede a que a transação pertence, o endereço do registro e sua abi, a functionName a chamar e os args já na ordem da chamada:

{
"walletRegisterAddress": "0x2222222222222222222222222222222222222222",
"abi": [],
"network": { "name": "Ethereum", "chainId": "1", "isTestnet": false },
"functionName": "setSplitWalletWithAuth",
"args": [
"12345",
"7",
"0x3333333333333333333333333333333333333333",
"0x1111111111111111111111111111111111111111",
true,
"0",
"1789834200",
27,
"0x...",
"0x..."
],
"expiresAt": "2026-09-20T12:10:00.000Z",
"signatureParams": {
"clientId": "12345",
"splitId": "7",
"token": "0x3333333333333333333333333333333333333333",
"wallet": "0x1111111111111111111111111111111111111111",
"active": true,
"nonce": "0",
"deadline": "1789834200",
"v": 27,
"r": "0x...",
"s": "0x..."
}
}

functionName é o nome do método do contrato de registro (presente na abi) que deve ser chamado: setClientWalletWithAuth para a carteira do negócio e setSplitWalletWithAuth para a carteira de um parceiro; não é preciso deduzir isso pela presença de splitId. Os signatureParams trazem os mesmos valores de forma nomeada, para integrações que preferem montar a chamada por conta própria, e expiresAt é a forma ISO 8601 de signatureParams.deadline.

A conta que envia a transação funciona apenas como relayer: ela paga o gas, mas não precisa ser a carteira cadastrada. Os parâmetros assinados impedem que essa conta altere o cliente, token, carteira, estado do parceiro ou prazo de validade.

A função abaixo pode ser usada tanto com um signer no servidor quanto com uma carteira do navegador. Os exemplos usam ethers v6:

import { Contract } from "ethers";

async function submitWalletAuthorization(authorization, signer) {
const { walletRegisterAddress, abi, functionName, args } = authorization;

if (new Date(authorization.expiresAt) <= new Date()) {
throw new Error("A autorização expirou; solicite uma nova");
}

const registry = new Contract(walletRegisterAddress, abi, signer);
const transaction = await registry[functionName](...args);

const receipt = await transaction.wait();
if (!receipt || receipt.status !== 1) {
throw new Error("A transação de registro falhou");
}
return receipt;
}

Envie a transação na rede indicada em network.chainId. O GET /api/currency-token informa o mesmo chainId por token, caso você precise dele antes de solicitar uma autorização. Uma autorização é válida por dez minutos e pode ser consumida apenas uma vez.

Pelo servidor ou relayer​

Mantenha a chave da API e a chave privada do relayer em variáveis de ambiente ou em um gerenciador de segredos. Use uma conta dedicada e abastecida apenas com o token nativo necessário para pagar as taxas das transações.

import { JsonRpcProvider, Wallet } from "ethers";

const apiResponse = await fetch(
`${process.env.BITPAYWAY_API_URL}/api/split/wallet`,
{
method: "PATCH",
headers: {
Authorization: `ApiKey ${process.env.BITPAYWAY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tokenContractId: "28a555aa-d6bb-4a0b-9266-0b6668f824b5",
wallet: "0x1111111111111111111111111111111111111111",
active: true,
}),
},
);

if (!apiResponse.ok) {
throw new Error(
`Não foi possível configurar a carteira: ${apiResponse.status}`,
);
}

const authorization = await apiResponse.json();
const provider = new JsonRpcProvider(process.env.BLOCKCHAIN_RPC_URL);

// Falha cedo quando o RPC do relayer aponta para uma rede diferente daquela para
// a qual a autorização foi assinada.
const connected = (await provider.getNetwork()).chainId;
if (connected !== BigInt(authorization.network.chainId)) {
throw new Error(
`O RPC está na chain ${connected}; use ${authorization.network.name} (${authorization.network.chainId})`,
);
}

const relayer = new Wallet(process.env.RELAYER_PRIVATE_KEY, provider);
const receipt = await submitWalletAuthorization(authorization, relayer);

console.log("Carteira registrada na transação", receipt.hash);

Para um parceiro, use PATCH /api/split/partners/{partnerId}/wallet; a função que envia a transação continua a mesma.

Pelo frontend com MetaMask​

O painel da Bitpayway já oferece esse fluxo com carteira do navegador para a carteira multidestino do cliente no token selecionado. Se você criar um frontend próprio, mantenha a chamada à API no seu backend, como mostrado abaixo.

Nunca coloque a chave da API da Bitpayway no código do frontend. Crie uma rota autenticada no seu próprio backend que chame o PATCH da carteira e retorne apenas a resposta de autorização. Neste exemplo, /seu-backend/autorizacao-carteira representa essa rota da aplicação.

import { BrowserProvider } from "ethers";

if (!window.ethereum) {
throw new Error("A MetaMask não está instalada");
}

const provider = new BrowserProvider(window.ethereum);
await provider.send("eth_requestAccounts", []);
const signer = await provider.getSigner();
const selectedWallet = await signer.getAddress();

// Esta chamada vai para o seu backend. Ele mantém a API key secreta e chama
// PATCH /api/split/wallet (ou o PATCH da carteira do parceiro) na Bitpayway.
const response = await fetch("/seu-backend/autorizacao-carteira", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
tokenContractId: "28a555aa-d6bb-4a0b-9266-0b6668f824b5",
wallet: selectedWallet,
active: true,
}),
});

if (!response.ok) {
throw new Error(`Não foi possível obter a autorização: ${response.status}`);
}

const authorization = await response.json();

// A autorização informa a que rede ela pertence, então a MetaMask pode ser
// trocada para ela em vez de pedir isso ao usuário.
await window.ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: `0x${BigInt(authorization.network.chainId).toString(16)}` }],
});

// Pegue um signer novamente: o anterior está ligado à rede de antes da troca.
const networkSigner = await new BrowserProvider(window.ethereum).getSigner();
const receipt = await submitWalletAuthorization(authorization, networkSigner);
console.log("Carteira registrada na transação", receipt.hash);

A MetaMask solicita ao usuário a aprovação da transação e mostra o custo de gas. Depois que o receipt indicar sucesso, consulte a rota /status correspondente pelo seu backend até que isEnabled seja true. Se a transação não for enviada antes do prazo, ou se o mesmo nonce já tiver sido consumido, chame a rota de autorização para obter uma nova resposta em vez de reenviar a anterior.

O cadastro da carteira do cliente deve ser feito separadamente para cada token, pois a chave on-chain inclui o cliente e o token. O cadastro da carteira de um parceiro também é específico por token e inclui ainda o vínculo do parceiro.