import { createPublicClient, createWalletClient, http, parseUnits } from "viem";
import { polygon } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { fetch } from "undici";
const USDC = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359";
const GATEWAY_WALLET = "0x77777777Dcc4d5A8B6E418Fd04D8997ef11000eE";
const GATEWAY_MINTER = "0x2222222d7164433c4C09B0b0D809a9b52C04C205";
const erc20 = [
{ type: "function", name: "decimals", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
{ type: "function", name: "approve", stateMutability: "nonpayable", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [{ type: "bool" }] },
];
const gatewayWalletAbi = [
{ type: "function", name: "deposit", stateMutability: "nonpayable", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [] },
];
const gatewayMinterAbi = [
{ type: "function", name: "gatewayMint", stateMutability: "nonpayable", inputs: [{ type: "bytes" }, { type: "bytes" }], outputs: [] },
];
const account = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`);
const rpc = http(process.env.POLYGON_RPC_URL);
const pub = createPublicClient({ chain: polygon, transport: rpc });
const wallet = createWalletClient({ chain: polygon, transport: rpc, account });
async function gatewayTransfer() {
// 1. Approve + deposit
const decimals = await pub.readContract({ address: USDC, abi: erc20, functionName: "decimals" });
const amount = parseUnits("25", Number(decimals));
await wallet.writeContract({ address: USDC, abi: erc20, functionName: "approve", args: [GATEWAY_WALLET, amount] });
await wallet.writeContract({ address: GATEWAY_WALLET, abi: gatewayWalletAbi, functionName: "deposit", args: [USDC, amount] });
// 2. Request attestation from Circle Gateway API
const res = await fetch("https://gateway-api.circle.com/v1/transfer", {
method: "POST",
headers: { "content-type": "application/json", authorization: `Bearer ${process.env.CIRCLE_API_KEY}` },
body: JSON.stringify({
burnIntent: {
spec: {
version: 1,
sourceDomain: 7, // Polygon domain ID
destinationDomain: 7, // same-chain "withdraw", or change for cross-chain
sourceContract: GATEWAY_WALLET,
destinationContract: GATEWAY_MINTER,
sourceToken: USDC,
destinationToken: USDC,
sourceDepositor: account.address,
destinationRecipient: "0xRecipient...",
value: amount.toString(),
},
},
}),
});
const { attestationPayload, signature } = await res.json();
// 3. Submit attestation to GatewayMinter
const tx = await wallet.writeContract({
address: GATEWAY_MINTER,
abi: gatewayMinterAbi,
functionName: "gatewayMint",
args: [attestationPayload as `0x${string}`, signature as `0x${string}`],
});
console.log("gatewayMint tx:", tx);
}
gatewayTransfer();