With Circle’s Programmable Wallets, merchants can quickly add USDC payments to their payment gateway. Read our guide to learn how.
With Circle’s Programmable Wallets, merchants can quickly add USDC payments to their payment gateway. Read our guide to learn how.
Setting up an on-chain checkout experience can be difficult for payment gateway providers. Not only do they have to manage the complexity of blockchain node infrastructure for transaction and data management, but they must also ensure that the experience is simple, fast, and easy for their users.
However, with Circle’s Programmable Wallets, merchants can quickly add USDC payments to their payment gateway. By combining Programmable Wallets with a fast, efficient blockchain like Avalanche or Solana, merchants can provide a streamlined, efficient, and user-friendly experience that rivals traditional card payments.
Let’s look at how to build this solution.
Enabling USDC Payments with Programmable Wallets
We’ll build our USDC payments solution with Circle’s Programmable Wallets APIs, and Gas Station. We’ll create a treasury wallet that receives the payments but then transfers the funds to a merchant wallet for a more permanent place to hold our total merchant funds.
- First, we’ll use Programmable Wallets to create our wallets. In this tutorial, we’ll use developer-controlled wallets, which give developers control over the wallet’s keys for management of funds. This allows payment providers to facilitate blockchain transactions on behalf of the merchant without needing to worry about private key management.
- Next, we’ll use our server-side Node.js SDK to call the APIs. This SDK abstracts away any differences across blockchains (e.g. Polygon PoS and Solana), which allows you to build transaction flows in a blockchain-agnostic way.
- Then, we’ll use the Gas Station feature, so that we don’t have to worry about the complexities of managing a paymaster or fee payer to sponsor transaction fees (known as gas) while moving funds from our treasury wallet to our merchant wallet.
Step 1: Set up Developer-Controlled Wallets
Let’s start by creating a treasury wallet where we’ll receive payments. In this example, we’ll create it as a developer-controlled wallet on Solana.
To do this, we need a wallet set. As the name suggests, this is a set of wallets that are controlled by the same cryptographic private key. Create the wallet set using the server-side SDK with the following script:
(Note: If you are new to Programmable Wallets, consider starting with this step-by-step tutorial for setting up user accounts, entity secrets, and so on.)
const { initiateDeveloperControlledWalletsClient } = require('@circle-fin/developer-controlled-wallets');
const sdk = initiateDeveloperControlledWalletsClient({
apiKey: '',
entitySecret: ''
});
const main = async () => {
const response = await sdk.createWalletSet({
name: 'Solana WalletSet'
});
console.log(response["data"])
}
main()
This will produce a response with our Wallet Set ID:
walletSet: {
id: '01904ab2-df1e-7218-b722-f779f0dfa711',
custodyType: 'DEVELOPER',
name: 'Solana WalletSet',
updateDate: '2024-06-24T14:42:34Z',
createDate: '2024-06-24T14:42:34Z'
}
Now let’s create our treasury wallet. We’ll pass in:
- Our newly created walletSetId
- Solana (SOL_DEVNET) as the blockchain
- EOA as the account type (on Solana we use Externally-Owned Accounts)
const { initiateDeveloperControlledWalletsClient } = require('@circle-fin/developer-controlled-wallets');
const sdk = initiateDeveloperControlledWalletsClient({
apiKey: '',
entitySecret: ''
});
const main = async () => {
const response = await sdk.createWallets({
accountType: 'EOA',
blockchains: ['SOL-DEVNET'],
count: 1,
walletSetId: ''
});
console.log(response["data"])
}
main();
Note that you can always view your wallets and transaction history with the Circle Console:
Step 2: Prepare to accept payments
Let’s get ready to accept a customer’s USDC payment into our treasury wallet.
First, we need to know our treasury wallet address to give to the customer for payment. This address is different from the wallet ID. You can get a list of your wallet addresses directly from Console or by using the following script:
// Import and configure the developer-controlled wallet SDK
const { initiateDeveloperControlledWalletsClient } = require('@circle-fin/developer-controlled-wallets');
const sdk = initiateDeveloperControlledWalletsClient({
apiKey: '',
entitySecret: ''
});
const response = await sdk.getWallet({id: '223d9a78-ca33-4cbd-ab83-8f083e3c045b'});
Step 3: Accept payment
Now we wait for the user’s USDC payment. We can check to see if payment has been made by querying our merchant wallet’s token balance, using the following script:
const response = await circleDeveloperSdk.getWalletTokenBalance({
id: ''
});
Note: To better manage payments, you can store the transaction session information in a database and include the payment intent and other relevant details. Once the transaction is recorded on the blockchain, you can update the database record with the block explorer link or other transaction details. This approach provides a comprehensive and detailed transaction history for each merchant wallet.
Step 4: Transfer funds to merchant account and use Gas Station to sponsor gas fees
Once the payment is complete, we don’t want the USDC sitting in our treasury wallet (or potentially thousands of our treasury wallets). Instead, we want the USDC routed into a single merchant wallet.
However, to transfer the USDC, we need to pay gas fees (in this case since we’re using Solana, we’ll need to pay in SOL). This can be a hassle when dealing with thousands of transactions and wallets. So we’ll use our Gas Station feature to make this easier.
Gas Station eliminates the need to obtain SOL and pay for gas for every individual transaction. Instead, you can pay for gas separately and with a currency of your choice (for example, USDC instead of SOL).
Solana wallets come with Gas Station support by default. Use a script such as the following to use Gas Station to transfer the USDC to the merchant wallet:
const response = await circleDeveloperSdk.createTransaction({
walletId: '',
tokenId: '',
destinationAddress: '',
amounts: [''],
fee: {
type: 'level',
config: {
feeLevel: 'MEDIUM'
}
}
});
We’re using several parameters here:
- walletId - the ID of the source wallet we are transferring from (our treasury wallet)
- tokenId - the ID of the token that will be transferred (in our case the ID for USDC)
- destinationAddress - the ID of our wallet we are transferring to (our merchant wallet)
- amount - the amount of tokens (in our case, USDC) to be sent
- feeLevel - A dynamic blockchain fee level setting (LOW, MEDIUM, or HIGH) used to pay gas for the transaction. This is calculated based on network traffic, supply of validators, and demand for transaction verification. Estimates for each fee level can be obtained through the estimate fee API call.
A Note on Block Confirmation
For a payment or transaction to be considered complete by a blockchain, you have to wait for several blocks to confirm after your transaction is accepted. This can introduce delays in payment confirmations. For example, when using Ethereum you might wait up to 3 minutes for a transaction to be considered complete.
Solana, though, is a great choice for merchant payments. It’s fast with a typical block confirmation time of only 400 milliseconds—a confirmation time comparable to card payments.
Conclusion
For a merchant services company looking to add USDC payments to their payment gateway, Circle’s Programmable Wallets offer a comprehensive and robust solution. Utilizing Solana’s advanced processing capabilities alongside the unique Gas Station feature enables a streamlined, efficient, and user-friendly payment experience.
Furthermore, Programmable Wallets enables you to dynamically scale to multi-asset and multi-blockchain infrastructure as your needs evolve for a future-proofed payment gateway.
*Circle Technology Services, LLC (“CTS”) is a software provider and does not provide regulated financial or advisory services. You are solely responsible for services you provide to users, including obtaining any necessary licenses or approvals and otherwise complying with applicable laws. For additional details, please click here to see the Circle Developer terms of service.