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 into GatewayWallet on Polygon
const decimals = await pub.readContract({ address: USDC, abi: erc20, functionName: "decimals" });
const amount = parseUnits("25", Number(decimals)); // example
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
// Build and sign a BurnIntent (EIP-712 typed data) for source=Polygon, destination=Polygon (same-chain "withdraw") or another chain.
// For brevity, assume you already produced `burnIntent` and EIP-712 signature with your EOA.
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: {
maxBlockHeight: "999999999999",
maxFee: "0",
spec: {
version: 1,
sourceDomain: 7, // Polygon PoS domain id (per Circle docs)
destinationDomain: 7, // or another supported domain id
sourceContract: GATEWAY_WALLET,
destinationContract: GATEWAY_MINTER,
sourceToken: USDC,
destinationToken: USDC,
sourceDepositor: account.address,
destinationRecipient: "0xRecipient...", // who receives on destination
sourceSigner: account.address,
destinationCaller: "0x0000000000000000000000000000000000000000",
value: amount.toString(),
},
},
// include your EIP-712 signature of BurnIntent here if required by your flow
}),
});
const { attestationPayload, signature } = await res.json();
// 3) Submit attestation to GatewayMinter on destination chain
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();