Arc House
Sign in or Join the community to continue

ArcShop with HJ: Building Chain Agnostic Apps with Circle Gateway and Circle Wallets

Posted Apr 30, 2026 | Views 1.7K
# Circle Gateway
# Gateway
# App Kits
# Circle Wallets
# Unified Balance Kit
Share

Speakers

user's Avatar
Hui Jing Chen
Senior Manager, Developer Relations and Ecosystem Marketing @ Circle
user's Avatar
Tim Baker
Community Manager @ Circle

SUMMARY

HJ from Circle DevRel walks through Circle Gateway, showing how developers can use unified USDC balances to build chain-agnostic applications across Arc and other supported networks. The session covers Gateway’s deposit and transfer model, burn intents, attestations, forwarding for gas abstraction, and support for both EVM and Solana flows. HJ also demos a sneak peak of the new Unified Balance Kit, which simplifies multichain deposits, balance checks, and transfers into a much cleaner SDK experience. The workshop ends with Q&A on SCA delegation, gas sponsorship, fees, finality, and agent-based automation.

+ Read More

TRANSCRIPT

HJ: "Hello, everyone. I'm HJ from the Circle DevRel team. For today's Arc Shop, we're doing a deep dive into one of Circle's interoperability primitives, one of my personal favorites: Gateway."

HJ: "This diagram gives you an idea of where Gateway sits within Circle's full-stack platform. We have Arc at the bottom as the underlying infrastructure layer, almost like the operating system. On top of Arc, you have stablecoins and tokenized assets, which are then supported by services that manage and move those assets. Gateway is one of those services, and it's also supported across numerous blockchains."

HJ: "For those of you who haven't heard of Gateway before, it's a relatively new primitive that allows a unified USDC balance across supported chains. Right now, we support twelve mainnets and thirteen testnets, and Arc is one of them."

HJ: "Think about receiving funds on different chains. Gateway lets you treat that USDC as one unified balance instead of keeping capital parked across multiple networks just to stay ready for activity. That gives you a faster cross-chain UX and reduces the amount of idle capital you need to pre-fund if you're supporting a multichain ecosystem."

HJ: "At a high level, Gateway works in three steps, although those steps don't always happen all at once. First, you deposit into a Gateway Wallet contract. That's how you establish the unified Gateway balance. Then, when you want to move funds out, you sign and execute the transfer."

HJ: "That's all the slides I have. The next slide should say 'Code Walkthrough,' so I'd like to trouble Tim to swap me over to my screen. Mr. Baker, please."

Tim Baker: "I take it you're not hearing me?"

HJ: "Hello? Tim, can you swap over to my screen? Yeah, great."

Tim Baker: "Yeah, sorry about that."

HJ: "No worries."

Tim Baker: "That was me. Sorry about that."

HJ: "No worries."


Gateway architecture and deposit flow

HJ: "This is a diagram. I'm not an artist, so it's stick figures, everybody."

HJ: "On-chain, Gateway is mainly two contracts: the Gateway Wallet, where USDC is deposited and balances are managed, and the Gateway Minter, which mints USDC on the destination chain."

HJ: "This first half here is the deposit flow. Users call the deposit function on the chain's Gateway Wallet contract. Circle's Gateway off-chain service observes finalized deposit events from those Gateway Wallet contracts and updates the balance ledger for the depositor address."

HJ: "If Bob has funds on Sei and Arc, for example, he can call the Gateway Wallet contract on Arc and say, 'I want to deposit X amount.' The off-chain ledger listens for that event and records the balance. That's the most straightforward way to deposit into Gateway."

HJ: "What makes Gateway interesting to me is that it's very flexible. You can also deposit on behalf of someone else using depositFor. In this diagram, Bob can call depositFor for Alice, and then Alice's balance gets credited. Alice becomes the depositor on Gateway and can access those funds."

HJ: "Once you establish your deposit in Gateway, you can move it out to the other supported chains. That's the transfer flow. Transfers are driven by something called burn intents, and those burn intents must be signed."

HJ: "The user signs the transfer parameters and sends them to the Gateway API via a POST request to the v1/transfer endpoint. Gateway validates the request against the off-chain balance ledger. If everything checks out, you get an attestation, and that attestation is what gets used on the destination chain to mint USDC."

HJ: "Source accounts can be smart contract accounts, or SCAs. However, even though they can deposit, they can't sign Gateway burn intents directly right now because Gateway does not currently accept EIP-1271 signatures for transfers."

HJ: "The team may add that in the future, but right now, if you want to use SCA wallets with Gateway, there is a delegate mechanism where you assign an EOA wallet as your delegate to sign transactions for you. So it is totally supported to use SCA wallets with Gateway."

HJ: "Another thing you can do with Gateway is use the forwarding service. If you don't want to worry about native gas tokens for minting on the recipient chain, Gateway supports the same forwarding service that's available for CCTP, where you let Circle handle the destination mint for a small forwarding fee. That's one reason I really like Gateway. It's very flexible."

HJ: "Okay, enough talk and enough diagrams. Let's look at some code."


EVM deposit demo

HJ: "The first code I'm going to show is an EVM deposit on Arc, which is the simplest raw Gateway deposit flow. The flow is simple: approve and then call deposit."

HJ: "It's very important that you call deposit and not a standard ERC-20 transfer. You must call deposit on the Gateway Wallet contract."

HJ: "This part is just setup, and this is the Gateway Wallet ABI. It's not too complicated. Then I use viem to set up the clients. Basically, you approve the amount you want to deposit and then deposit that amount."

HJ: "So let's run it."

HJ: "Whoa. Oh, come on. Transaction pool is full. That did not happen in the afternoon. This is an issue that happened earlier with some other people on Arc. Okay, let's try it again."

Tim Baker: "That's a new one to me."

HJ: "Yeah. Some people reported this happening today. Can I swap Arc out with someone else? Maybe. Who's fast? I don't know. Maybe Sei. Let's try."

HJ: "This may or may not work. Ignore this because I just changed the chain name. I did not pray to the live demo gods, guys."

Tim Baker: "Looks like it's working now."

HJ: "Yeah, no, it's not. Oh boy. I think I need the USDC address for Sei. Hang on. If I could remember the USDC address by heart, I wouldn't be working in this role anymore."

HJ: "USDC contract address. Let's go. Come on, Google."

Tim Baker: "The live chat..."

HJ: "Did someone helpfully post it?"

Tim Baker: "Oh, sorry. On our side."

HJ: "Okay, hang on. I think I got it. At least y'all know this is not prerecorded and totally real."

Tim Baker: "That's all right. We like to show the real developer experience."

HJ: "Yeah. So that's pretty much how it works. As you can see, you do need the correct USDC address for this to work."

HJ: "I printed here that the unified balance updates after source-chain finality. The reason I was thinking so hard about which chains are fast is that some chains, like Sei and Arc, are really fast to finality. But if you're doing it on Ethereum, Base, or World Chain, they take much longer to confirm their blocks."

HJ: "So the deposit could take anywhere from about five to fifteen minutes to finalize. That's something to look out for, and we do have those timings in our documentation."


Solana and Circle Wallets deposit demos

HJ: "The next script I want to show is for Solana, because we do support Solana. Solana code in general is always a little heavier than EVM code because viem does a lot of heavy lifting, but the deposit script still looks reasonable."

HJ: "Wait until you see the transcript, guys. Never mind. Let's run it anyway."

HJ: "It's the same concept. You set things up, define the PDAs and the Anchor configuration, and then call deposit on the Gateway Wallet contract that's deployed on Solana. So it's a very similar flow."

HJ: "Another flow you can use for Gateway is through Circle Developer Controlled Wallets. For that, you'll need the Developer Controlled Wallets SDK, and you'll need to set up your Circle account, API key, and entity secret."

HJ: "With Circle Wallets, what you use to call contracts is the SDK function createContractExecution. Even though the methods are different, the flow is the same. You approve the transaction, and then once it's approved, you call deposit. Again, you can see right here that you call deposit."

HJ: "The reason I'm showing these three different scripts is to reinforce that even though it's a different flow, different chain, or different wallet type, the concept for depositing USDC is the same. Later, when you see transfer, it's pretty much the same idea too. It's mostly a matter of using the right stack."

HJ: "So let's run this. I'm running this on Arc. Please work. I hope that transaction pool thing was an anomaly."

HJ: "Now it works. Interesting. Something's going on with Arc testnet today. I was talking to an Arc engineer earlier. There's something happening, but it's okay. Side note: if any of you run into that problem today, let us know so we can investigate."


Transfer flow and forwarding service

HJ: "So that's deposit. Now we've deposited balance into Gateway, and we want to transfer it out."

HJ: "If you use the forwarding service, it's honestly a lot easier because then you don't have to worry as much about whether you have gas tokens on your recipient chain. So this script, again hopefully it works out, is going to transfer to Base Sepolia."

HJ: "This part is just TypeScript. Don't worry about it. I'm going to transfer one USDC."

HJ: "This is the information for Arc, the information for Base, and this is the burn intent I was talking about earlier in the diagram. These are the transfer specs required by Gateway. This is essentially the information Gateway needs to verify that you own the balance and that it's okay for you to transfer it."

HJ: "It's pretty readable, which is great. You have your source domain, destination domain, your contract addresses, and your source depositor. If you deposit to your own wallet by calling deposit, then the source depositor is your wallet. If you use depositFor, then the source depositor is the wallet you deposited for."

HJ: "So the source depositor determines who has access to the funds. Then you have the burn intent. I have a function that formats the burn intent and builds the transfer spec in the format the Gateway API expects."

HJ: "Because this particular script uses the forwarding service, the way you enable it on the Gateway API is by adding the flag enableForwarder=true to the request. That tells Gateway that you do want to use the forwarding service. Then it's a POST request, and you send the formatted transfer spec as the payload."

HJ: "Because it's forwarding, you should estimate the forwarding fee first to make sure everything goes through. Then you submit the forwarded transaction. The first function is for the estimate, and the second function actually submits to the Gateway API to get the attestation back. It's the same request endpoint and payload."

HJ: "Instead of polling for the attestation, you poll the transfer ID. I have some logic for the different statuses. If it's finalized or confirmed, you'll have the mint transaction hash because it has gone through. If it's a failure, you can go check what happened. If you took too long before minting, the attestation can expire."

HJ: "There is some way to recover. I'll have to check whether it's similar to recovery in CCTP or not. If anyone is curious about that, I'll go check and see whether we document it clearly in the docs."

HJ: "But that's just a run-through of how the script looks. So I'm going to run it. We're going to forward from the Gateway balance to a recipient on Base Sepolia."

HJ: "Like I mentioned, it estimates the forwarding fee. It's about 0.2 USDC. It signs the burn intent before submitting to the Gateway API."

HJ: "Because we used the forwarder, Gateway gives us back this transfer ID, which we can then poll."

HJ: "As you can see, even though Base Sepolia is a slower-finality chain, for the transfer it's still near-instant. One USDC has been forwarded to Base Sepolia."

HJ: "We probably can't look at it because I'm sharing a window, but essentially you'll get the transaction hashes returned. If you're building out a UI, you can always display a link so users can inspect the transaction."

HJ: "So that's for EVM chains. If you're going to do it on Solana, I also suggest using the forwarding service if you don't mind paying a bit of an extra fee. It is slightly more code than the EVM transfer simply because of all the setup. You need the PDAs and the IDLs for Solana."

HJ: "But it's still conceptually similar. You build the transfer spec, sign it, get the attestation, and mint. The speed is about the same no matter what chain you're transferring to."


Raw Solana transfer and Unified Balance Kit

HJ: "I included the raw Solana transfer script on purpose because it leads into something else."

HJ: "If you were to write the whole thing yourself - construct the burn intent, sign it, and then mint on the destination chain - it's longer. You have to do a lot of setup code, handle layouts and IDLs, and I threw in a few helper functions because otherwise it gets even messier."

HJ: "You also have to encode the burn intent and sign it, because that's what Solana needs you to do. And again, there's PDA setup."

HJ: "I will admit that I'm not very experienced with Solana, so I do respect all the Solana developers tuning in. We'll absolutely take suggestions on how to make the documentation better as well."

HJ: "By the time you get to the point where you need to create and sign the burn intent, I'm already about three hundred lines in. That's just the nature of using TypeScript with Solana. Maybe if you do it in Rust it's less code - I don't know, because I don't know Rust. Sorry."

HJ: "But the flow is the same. You take your signed burn intent, submit it to the Gateway API, grab the attestation, and then use the attestation to call mint with the Gateway Minter contract. So let's hope this works."

HJ: "This is actually the raw Gateway API response. When it comes back, you get an attestation, a transfer ID, and so on. The attestation is used to mint the funds on Solana. If it's successful, you get a nice transaction hash."

HJ: "So that's about four hundred lines of code. But what's important is that we recently released something called Unified Balance Kit. Yes, that's what it's called: Unified Balance Kit."

HJ: "Unified Balance Kit abstracts away a lot of that lower-level infrastructure code. If any of you have used Bridge Kit before, or even SwapKit from our latest AppKit release, the interface is very similar."

HJ: "You install and import the kit, instantiate a new instance, and then set up adapters. For this single deposit script, I'm going to deposit from both Arc and Solana. If I'm doing Arc, I'm going to use the viem adapter. If I do Solana, I'm going to use the Solana adapter."

HJ: "Then you call the deposit function from your kit instance. The parameters you need to provide are the adapter, the chain, the amount you want to deposit, and the token. For now it's just USDC. In the future, we may support more than just USDC. Nothing is confirmed on the roadmap, but that's why the option is there."

HJ: "So you call deposit and just run it. The best part is that for Solana it's literally the same interface. Just swap the adapter and swap the chain name, and it's the same interface."

HJ: "Let's run this. It's fifty-five lines."

Tim Baker: "Love it."

HJ: "This is the response that the SDK gives you. You get all of this information. I'm not going to go into more detail because I want to show you the transfer flow too."

HJ: "That was the deposit. Once you've established the balance, when you need to transfer out, you want to transfer."

HJ: "With Unified Balance Kit, same setup. The kit offers this getBalances function that you can use to check balances. Again, you provide the sources you want to check. If it's testnet, you need to specify testnet. Otherwise, I think it defaults to mainnet. You can also include pending balances."

HJ: "You know what? I'm not going to go into that much detail. This is just a teaser because my colleague Elton will be going through Unified Balance Kit much more in-depth on Friday, so you have to tune into his session. But just for completeness, I'm going to run this script and hopefully it doesn't fail. I don't want a fail sandwich."

HJ: "Essentially, in order to transfer, you only need to call spend. That's it. The kit abstracts away all of those four hundred lines, even for Solana."

HJ: "This is what the SDK can return when you check the Gateway balance. You can check balances across all supported chains."

HJ: "And when you call spend, this is the result that's returned. I think it's really neat because all of this information is really helpful. In a past life, I was mainly a UI developer, so this is the kind of information that would be really useful on the frontend of your application. Of course, it's useful on the backend as well."

HJ: "So that's pretty much it for the scripts. I did try to go a little faster because I knew people would have questions, so I was trying to compress everything."


Q&A

HJ: "So I left a little bit of time for questions. Tim and Mike, how are we on time?"

HJ: "In the meantime, before I hear them talk to me, I can show you the difference. With getBalances, it's just a function. If I were to check my balances manually, it would be longer. You'd have to maybe use viem to check your own wallet addresses, and then for Gateway there is a getBalances endpoint if you didn't use the kit."

HJ: "Anyway, Mike and Tim, do we have any questions, or are people just totally confused by what I just said for the past half hour? Show my pretty diagram again."

Tim Baker: "Can you hear me?"

HJ: "Yes."

Tim Baker: "There we go. Sorry. We've got a few questions here. Let me go through them."

HJ: "Okay."

Tim Baker: "There seems to be some hang-up around the differences between EVM and Solana, which is a deep topic. I saw a couple of people ask if we could explain it again. Let me find the exact question."

HJ: "Okay."

Tim Baker: "Before I get to that, somebody asked: 'Arc uses an EOA wallet just like Sei. So why does Base get a smart contract account instead? What does that tell us about Arc's account model?'"

HJ: "Oh, that diagram was just an example. For Circle Wallets, I think we have eight chains supported - embarrassing if I get that wrong. But this isn't specific to Base. It could be any of the supported chains using an SCA wallet."

HJ: "The diagram was just meant to show that if you use an SCA wallet as your depositor, you need an EOA delegate that will sign the transactions for you when you want to transfer out. That could be Arc, Polygon, Avalanche, Ethereum, or another supported chain."

Tim Baker: "It could be Arc as well."

HJ: "It could be Arc as well. Correct, because Circle Wallets does support Arc. The point is simply that if you are using an SCA wallet as your depositor, you do have to assign an EOA delegate wallet to do the signing for you when you want to transfer out. That's all."

Tim Baker: "Makes sense. Let's see. I've got another one here. Dessetti from Wizpay says: 'Noticing those EVM and Solana scripts in your sidebar and building a payroll bot. Can Gateway automatically handle the destination gas when routing USDC from Arc to Solana, or do I need to fund the account manually?' I'm guessing they're talking about account sponsorship."

HJ: "That's why I wanted to mention the SCA wallet flow. If you use Circle Wallets - Circle SCA Wallets - you have the option to make use of Gas Station for gas sponsorship, because Gas Station is essentially powered by Circle Paymaster under the hood. That allows you to sponsor gas on the deposit side."

HJ: "If you couple that with the forwarder, you can essentially abstract away the native gas token requirement and just use USDC."

HJ: "I do have a blog post on that. It's live on the Circle blog. I can't remember the exact title - something like 'Abstract Gas for Unified Balance' - but the flow is based on using SCA wallets."

HJ: "So that's why the EOA delegate information is important. If you use SCA wallets for the deposit, you can sponsor gas there. Then on the mint side, you can use the forwarding service, so you don't have to worry about native gas tokens on either end. Does that make sense?"

Tim Baker: "I think it does."

HJ: "Okay."

Tim Baker: "Let's see if he replies. In the meantime, we can move on to the next one. 'After a burn intent is signed on Gateway, is the user's balance locked until the attestation is returned, or does it remain available during that window?'"

HJ: "Fun question. I have to get back to you on that because I haven't thought through the exact timing closely enough. The time between submitting the transaction and the actual transfer is usually quite short, but I can't give you a factually accurate answer without checking with the engineers."

HJ: "So I will note that down. If the person who asked is on Discord or Arc House, is there some way we can get back to them? Otherwise I can just post when I find the answer."

Tim Baker: "Yeah, absolutely. Their name was Senna, and they're here on Arc House."

HJ: "Oh, great. I'll post on the forum then. That's fun."

Tim Baker: "Yeah, absolutely. Let's see. I see a few more here if we have time. Yeah, I think we've got a few minutes. 'Will there be opinionated security patterns or audits recommended specifically for apps using burn intents and wallet execution together?'"

HJ: "Using burn intents and wallet execution together? I don't fully understand the question."

Tim Baker: "That's fair. Maybe we can ask AmorX for some more detail on what they're looking for there. In general, though, pretty much any app that gets built - even with our products - if it's not strictly our code, you probably need to undergo audits."

HJ: "Your own audit, yeah. Probably."

Tim Baker: "But our code is audited."

HJ: "Yeah, you're right. Our contracts - the Gateway Wallet contract and the Gateway Minter contract - are audited. But we don't audit other people's code."

Tim Baker: "Here's an interesting one. 'For Unified Balance Kit, what's the latency and cost model when it comes to aggregating balances across five chains in real time? If I'm building a DeFi app that needs to check liquidity before a swap, will each balance call trigger on-chain RPCs, or does Circle cache or index it, and who pays the gas?'"

HJ: "Yeah. How do I read it?"

Tim Baker: "On the page we're streaming from, there's a thing that says 'private chat.'"

HJ: "There we go. So, what's the latency and cost model when aggregating balances across five chains? The fee is when you transfer, and it's based on the source chain. If I deposit into the Arc ledger and I also deposit into, say, the Ethereum ledger, then when I do the transfer out, the fee is based on which source balance I'm spending from. So if I transfer out from my Ethereum ledger balance, that's a different fee."

HJ: "We do have the Gateway fees listed in the developer documentation. The last time I checked, Ethereum was probably the most expensive chain."

HJ: "One flow I've thought about, and written about before, is that if you have funds on a lot of different chains, one option - not the only option, just one option - is to use CCTP to sweep everything into an Arc balance, and then deposit that balance into Gateway. I think the Gateway fee for Arc is probably one of the cheapest. So that gives you a cheaper route when transferring out to the other supported chains from Arc."

HJ: "If you're building a DeFi app that needs to check liquidity before every swap, and you're asking whether each balance call will trigger on-chain RPCs, that's a good question. I need to double-check exactly how getBalances is returned."

Tim Baker: "I think it's coming from our API, but I'm not 100 percent sure. For permissionless flows, you'd probably need to call every chain."

HJ: "Because the funds you deposit are tracked using Circle's off-chain Gateway ledger, and the funds are locked in the Gateway Wallet contract."

HJ: "These are very good questions. It's definitely making me think about whether we want to add more notes to the developer documentation. So again, if I didn't directly answer your question, I'm sorry, but you are helping us make the docs better when I go dig up those answers."

HJ: "Any other fun questions, Tim?"

Tim Baker: "I am scrolling here looking. There are a lot of messages here."

HJ: "I see Mike dropped. I'm just reading the last one I can see: 'Can an AI agent use the UVK to autonomously move USDC between chains based on where it needs to pay?' I don't see why not."

HJ: "Your agent could definitely do it if you set it up correctly and give it the necessary credentials for signing. I don't see why not. That's my off-the-top-of-my-head answer, though. I haven't tried it yet."

Tim Baker: "Let's see if I've got one here."

HJ: "One last question. Let's go."

Tim Baker: "I did have one in it. Here it is: 'In Circle Wallets, what do we actually use as gas to deposit to Gateway? So let's say, on Solana or Base, would we deposit those native tokens, or would we be depositing USDC?'"

HJ: "The Gateway deposit is only USDC. Native tokens are only used for gas. If you're not doing gas sponsorship, and you're trying to deposit from something like a MetaMask wallet on Sei, then you would still need native Sei tokens to make that deposit call. But what you deposit into Gateway is USDC."

Tim Baker: "I think that makes sense."

HJ: "That's my answer."

Tim Baker: "Does that answer your question, CFA?"

HJ: "Are we at time? Was this scheduled to cut off on you?"

Tim Baker: "You know what? We are, actually. We're at time. So unfortunately, no more questions, but we're online all the time. Feel free to send us messages on the forums, DM us here on Arc House, or come see us on Discord."

HJ: "Yeah, 100 percent. We'll try to get to them. I'm just happy that anyone bothered to show up to listen to me talk about Gateway."

Tim Baker: "Oh, you've got, like, a hundred people watching you. I love it."

HJ: "Yeah. If five hundred people saw the Arc transaction pool was full, oh dear. But this is a good reminder that I need to follow up with one of the engineers I was talking to earlier."

HJ: "Still, thank you all so much for choosing to spend your morning, evening, or afternoon - whatever time zone you're in - with us."

HJ: "And let's see... Tim and Mike, maybe we can work together to list out some of the unanswered questions and post them as a post-workshop forum post or something."

Tim Baker: "I think that would be a great idea. I saw a few more come in, so yeah, we'll definitely get to that and put together a forum post with those answers. Thank you so much."

HJ: "Thank you all."

+ Read More
Sign in or Join the community
Building the global internet economy
Arc House
Create an account
Building the global internet economy
Comments (61)
Popular
avatar


Watch More

Using Circle Wallets to Send and Manage USDC
Posted Jan 21, 2026 | Views 18.2K
# Circle Wallets
# Stablecoin 101
Using Circle Developer Controlled Wallets to Send and Manage USDC
Posted Jan 21, 2026 | Views 18.6K
# Dev-Controlled Wallets
# Circle Wallets
# Stablecoin 101
# Demo
# developer tools
# developer quickstarts
# Developer
Terms of Service
Your Privacy Choices