Working code examples and tutorials for Fairway integration
Build a liquidity pool that only accepts deposits from KYC-verified users
use aiken/list
use fairway/compliance.{verify_kyc, PolicyDatum}
validator kyc_gated_pool {
fn spend(datum: PolicyDatum, _redeemer: Data, ctx: ScriptContext) {
let tx = ctx.transaction
let policy_id = datum.policy_id
// Verify all inputs have valid KYC tokens
list.all(tx.inputs, fn(input) {
verify_kyc(policy_id, input.output.address)
})
}
fn mint(_redeemer: Data, ctx: ScriptContext) {
let tx = ctx.transaction
// Only allow minting if depositor is KYC verified
verify_kyc("institutional_kyc_v1", tx.inputs)
}
}
import { FairwayClient } from '@fairway/sdk'
import { Lucid, Blockfrost } from 'lucid-cardano'
const fairway = new FairwayClient({
apiKey: process.env.FAIRWAY_API_KEY
})
const lucid = await Lucid.new(
new Blockfrost("https://cardano-mainnet.blockfrost.io/api/v0", "your_key"),
"Mainnet"
)
async function depositToPool(userAddress: string, amount: bigint) {
// Check KYC eligibility first
const eligibility = await fairway.checkEligibility(userAddress)
if (!eligibility.eligible) {
throw new Error(`User not eligible: ${eligibility.reason}`)
}
// Build transaction with KYC proof
const tx = lucid.newTx()
.payToContract(poolAddress, datum, { lovelace: amount })
.attachMetadata(674, { kyc_proof: eligibility.proof })
return await tx.complete()
}
Implement compliance verification using ERC-3643 tokens and Ethereum Attestation Service
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@fairway/contracts/PolicyEngine.sol";
import "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol";
contract ComplianceDeFi {
PolicyEngine public immutable policyEngine;
IEAS public immutable eas;
bytes32 public immutable kycSchemaUID;
constructor(
address _policyEngine,
address _eas,
bytes32 _kycSchemaUID
) {
policyEngine = PolicyEngine(_policyEngine);
eas = IEAS(_eas);
kycSchemaUID = _kycSchemaUID;
}
modifier onlyCompliant(address user) {
require(
policyEngine.isEligible(user, "institutional_kyc"),
"User not compliant"
);
_;
}
function stake(uint256 amount) external onlyCompliant(msg.sender) {
// Verify EAS attestation
bytes32 attestationUID = policyEngine.getAttestationUID(msg.sender);
Attestation memory attestation = eas.getAttestation(attestationUID);
require(attestation.schema == kycSchemaUID, "Invalid KYC schema");
require(attestation.expirationTime > block.timestamp, "KYC expired");
// Proceed with staking logic
_stake(msg.sender, amount);
}
}
import { FairwayClient } from '@fairway/sdk'
import { ethers } from 'ethers'
// Note: API key should be handled server-side for security
// This example shows client-side usage for demonstration only
const fairway = new FairwayClient({
apiKey: 'your_api_key_here', // Use server-side API for production
network: 'ethereum'
})
async function checkComplianceAndStake(userAddress: string, amount: string) {
try {
// In production, make this call from your backend API
// Example: const eligibility = await fetch('/api/check-eligibility', { ... })
const eligibility = await fairway.checkEligibility(userAddress)
if (!eligibility.eligible) {
throw new Error(`Compliance check failed: ${eligibility.reason}`)
}
// Connect to contract
const contract = new ethers.Contract(
contractAddress,
contractABI,
signer
)
// Execute stake with compliance verification
const tx = await contract.stake(ethers.parseEther(amount))
await tx.wait()
return { success: true, txHash: tx.hash }
} catch (error) {
return { success: false, error: error.message }
}
}
// pages/api/check-eligibility.ts (Next.js API route)
import { FairwayClient } from '@fairway/sdk'
const fairway = new FairwayClient({
apiKey: process.env.FAIRWAY_API_KEY, // Server-side only
network: 'ethereum'
})
export default async function handler(req, res) {
const { userAddress } = req.body
try {
const eligibility = await fairway.checkEligibility(userAddress)
res.status(200).json(eligibility)
} catch (error) {
res.status(500).json({ error: 'Compliance check failed' })
}
}
// Frontend usage
async function checkCompliance(userAddress: string) {
const response = await fetch('/api/check-eligibility', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userAddress })
})
return response.json()
}
Tokenize real-world assets with compliance across Cardano and EVM chains
// Cardano side (Aiken)
validator rwa_wrapper {
fn mint(redeemer: MintRedeemer, ctx: ScriptContext) {
let tx = ctx.transaction
expect MintRedeemer {
kyc_proof,
asset_id,
jurisdiction
} = redeemer
// Verify KYC for asset jurisdiction
verify_kyc_jurisdiction(kyc_proof, jurisdiction) &&
verify_asset_custody(asset_id, tx.mint)
}
}
// Ethereum side (Solidity)
contract RWABridge {
mapping(bytes32 => bool) public cardanoProofs;
function mintFromCardano(
bytes32 cardanoTxHash,
uint256 amount,
bytes calldata kycProof
) external {
require(!cardanoProofs[cardanoTxHash], "Already processed");
require(verifyKYCProof(msg.sender, kycProof), "Invalid KYC");
cardanoProofs[cardanoTxHash] = true;
_mint(msg.sender, amount);
}
}
Test your compliance integration with mock KYC data
import { FairwayClient } from '@fairway/sdk'
describe('Compliance Integration', () => {
let fairway: FairwayClient
beforeEach(() => {
fairway = new FairwayClient({
apiKey: 'test_key',
network: 'testnet',
mockMode: true
})
})
test('should allow compliant user to stake', async () => {
// Mock compliant user
const mockUser = 'addr_test1compliant'
fairway.setMockEligibility(mockUser, {
eligible: true,
reason: 'KYC1_OK',
compliance_level: 'institutional'
})
const result = await fairway.checkEligibility(mockUser)
expect(result.eligible).toBe(true)
})
test('should reject non-compliant user', async () => {
const mockUser = 'addr_test1blocked'
fairway.setMockEligibility(mockUser, {
eligible: false,
reason: 'SANCTIONS_HIT'
})
const result = await fairway.checkEligibility(mockUser)
expect(result.eligible).toBe(false)
expect(result.reason).toBe('SANCTIONS_HIT')
})
})