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.