Send fiat through the payment method specified in your intent:
// From your intentconst intent = await orchestrator.getIntent(intentHash);// Calculate exact fiat amount to sendconst fiatAmount = intent.amount .mul(intent.conversionRate) .div(ethers.utils.parseEther("1"));const amountToSend = ethers.utils.formatUnits(fiatAmount, 6);console.log(`Send ${amountToSend} to the maker via payment app`);
Make the payment through your Venmo/PayPal/etc. app to the maker’s account.
2
Request attestation
Submit your payment receipt to the attestation service:
// This is a simplified example - actual implementation varies by serviceconst attestationResponse = await fetch( 'https://attestation-service.zkp2p.xyz/attest', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ intentHash: intentHash, paymentMethod: 'venmo', transactionId: 'venmo-tx-id-from-receipt', amount: amountToSend, // Additional payment proof data }) });const { attestation } = await attestationResponse.json();console.log('Received attestation:', attestation);
3
Prepare verification data
Format the attestation for on-chain verification:
// Attestation is an EIP-712 signed messageconst paymentProof = attestation.signature; // The signed attestation bytesconst verificationData = attestation.metadata || "0x"; // Additional data
When using post-intent hooks, the USDC is transferred to the hook contract instead of directly to intent.to. The hook then executes custom logic (bridging, swapping, etc.).
In case of issues, the depositor can manually release funds to you:
// Depositor calls this if fulfillment fails but you completed paymentawait orchestrator.connect(depositorSigner).releaseFundsToPayer(intentHash);// This transfers the full intent amount (minus fees) directly to intent.to// Bypasses payment verification
Only the deposit owner can call releaseFundsToPayer. This is a safety mechanism for exceptional circumstances.
Important: Anyone can submit a fulfillment transaction, not just the intent owner:
// Relayer can fulfill on behalf of takerawait orchestrator.connect(relayerSigner).fulfillIntent({ intentHash: intentHash, // Taker's intent paymentProof: paymentProof, // Taker's proof verificationData: verificationData, postIntentHookData: "0x"});// Funds still go to intent.to (the taker)// This enables gasless fulfillment via relayers