Payouts

API to convert stablecoins to fiat money.

What is a payout?

A payout is an operation that moves funds from the sender's wallet to the receiver's bank account.

The payout can only be executed if a quote was created previously, and you have 5 minutes to execute the payout before the quote expires.

Please review how BlindPay manages the stablecoins in the flow of funds explanation.

How to mint USDB?

USDB is a fake ERC20 stablecoin powered by BlindPay to simulate payouts on development instances.

EVM Chains

You can mint infinite USDB, but you need to add Ether to your wallet, so please get some Ether from https://www.alchemy.com/faucets/base-sepolia.

Put your instance_id on the following url https://app.blindpay.com/instances/<instance_id>/utilities/mint and mint USDB on Base Sepolia Testnet.

Stellar

You can also mint USDB on Stellar Testnet.

If you don't have the USDB asset on your wallet, you can create a trustline by calling the following endpoint: Put your address on the following url https://api.blindpay.com/v1/blochain-wallets/{address}/create-asset-trustline.

Put your address on the following url https://api.blindpay.com/v1/blochain-wallets/{address}/mint-usdb and mint USDB on Stellar Testnet.

Remember that the address must be the same address that you used to create the blockchain wallet on the blockchain wallets section.

Approving tokens for being moved by BlindPay

All stablecoins supported by BlindPay are ERC20 tokens, so you need to call the approve method on the token contract to allow BlindPay to move the funds from any blockchain wallet.

Before approving the tokens, you need to have:

  1. A RPC provider URL from Base Sepolia Testnet
  2. A blockchain wallet with enough funds to execute the transaction
  3. The private key or any way to instantiate the blockchain wallet using ethers.js
  4. ERC20 token contract address (Provided by BlindPay on Quote API response)
  5. ERC20 ABI (Provided by BlindPay on Quote API response)
  6. BlindPay smart contract address (Provided by BlindPay on Quote API response)

To simulate an approval, we're going to use JavaScript to install express.js server and ethers.js library.

Before start, please ensure you have Node.js installed.

Now create a folder called approve-erc20. Inside the folder, please run the following command:

npm init

And now install the dependencies:

npm install express ethers

Now create a file called index.js inside it, paste the code below and replace the values with your own.

index.js
import express from "express";
import { ethers } from "ethers";

var app = express()

app.get("/", async function(req, res){
  // Before start
  const rpcProviderUrl = "<Replace this>" // You can get this from https://chainlist.org/?search=base&testnets=true
  const walletPrivateKey = "<Replace this>" // This wallet must have ethers (which you can get here: https://www.alchemy.com/faucets/base-sepolia) and USDB (which you can get here https://app.blindpay.com/instances/<instance_id>/utilities/mint) to execute the transaction on step 2
  const instanceId = "<Replace this>"
  const blindpayApiKey = "<Replace this>"
  const bankAccountId = "<Replace this>"

  // BlindPay Api Configs
  const headers = {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${blindpayApiKey}`
  };

  // 1 Step: Create a quote
  const fiftyDollars = 5000
  const quoteBody = {
    "bank_account_id": bankAccountId,
    "currency_type": "sender",
    "cover_fees": false,
    "request_amount": fiftyDollars,
    "network": "base_sepolia", // "sepolia", "base_sepolia", "arbitrum_sepolia", "polygon_amoy"
    "token": "USDB" // on development instance is always "USDB"
  }
  const createQuote = await fetch(`https://api.blindpay.com/v1/instances/${instanceId}/quotes`, { headers, method: "POST", body: JSON.stringify(quoteBody) });
  const quoteResponse = await createQuote.json();

  // 2 Step: Approve tokens
  const provider = new ethers.JsonRpcProvider(rpcProviderUrl, quoteResponse.contract.network)
  const yourWallet = new ethers.Wallet(walletPrivateKey, provider)
  const contract = new ethers.Contract(quoteResponse.contract.address, quoteResponse.contract.abi, provider)
  const contractSigner = contract.connect(yourWallet)

  const result = await contractSigner.approve(
    quoteResponse.contract.blindpayContractAddress,
    quoteResponse.contract.amount,
  );

  res.send({
    hash: result?.hash,
    quoteId: quoteResponse.id,
  });
});

/* istanbul ignore next */
app.listen(3000);
console.log("Express started on port 3000");

Now run you can run the code using the following command:

node index.js

Now access http://localhost:3000 and after some seconds you should see a result like this in your browser:

{"hash":"0x1ab66830a4804d80251f01b9d31c054a42068f5783c80d165507cddce0ac78ca","quoteId":"qu_lxrCXUOOyrem"}

Creating a payout on EVM chains

You can check the required fields in the BlindPay API Docs.

Before creating a payout, you need to:

  1. Create an account on BlindPay
  2. Create a development instance
  3. Create your API key
  4. Create a receiver
  5. Add a bank account
  6. Generate a quote
  7. Approve the tokens
cURL
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payouts/evm \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "quote_id": "qu_000000000000",
  "sender_wallet_address": "<Replace this>"
}'

Creating a payout on Stellar

You can check the required fields in the BlindPay API Docs.

Authorizing a token on Stellar

cURL
curl --request POST \
  --url https://api.blindpay.com/v1/instances/{instance_id}/payouts/stellar/authorize \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "quote_id": "qu_000000000000",
  "sender_wallet_address": "<Replace this>"
}'

This endpoint will return a transaction hash that you can use to execute the payout.

{
  "transaction_hash": "AAA...AAA"
}

With this hash we can create the transaction on Stellar.

First, you need to install the dependencies:

npm install @stellar/stellar-sdk

Now create a file called index.js inside it, paste the code below and replace the values with your own.

import {
  AuthRequiredFlag,
  AuthRevocableFlag,
  BASE_FEE,
  Horizon,
  Keypair,
  Networks,
  Operation,
  TransactionBuilder,
  Asset,
} from "@stellar/stellar-sdk";

const stellar = new Stellar({
  server: 'https://horizon-testnet.stellar.org',
  network: 'testnet',
});

const stellarWallet = stellar.wallet(Keypair.fromSecret(process.env.STELLAR_SECRET_KEY));

// Create a transaction from the hash that we got from the authorize endpoint
const transaction = TransactionBuilder.fromXDR(transactionHash, Networks.TESTNET);

// Sign the transaction
const signedTransaction = stellarWallet.sign(transaction);

// Submit the transaction
const result = await stellar.submitTransaction(signedTransaction);

console.log(result);

// You need to save the hash from the result (result.hash) to create the payout on BlindPay

::

Now run you can run the code using the following command:

node index.js

Now you can create the payout on BlindPay using the hash that you got from the result.

cURL
curl --request POST \
  --url https://api.blindpay.com/v1/instances/in_000000000000/payouts/stellar \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "quote_id": "qu_000000000000",
  "signed_transaction": "<Replace this>", // This is the signed transaction that we got from the authorize endpoint
  "sender_wallet_address": "<Replace this>" // This is the wallet address that we used to approve the tokens
}'

Testing scenarios

By default all the payouts are automatically completed in 'development' instances, but you can force 'refund' and 'failed' scenarios by adding specific values to the payout amount.

AmountResult Status
666.00Failed
777.00Refunded