Skip to main content

Time-Locked Release Example

Complete example of implementing time-based payouts with automatic fund release.

Overview

Time-locked releases automatically release funds after a specified time period. Perfect for:

  • Subscription payments
  • Recurring services
  • Delayed payouts
  • Trust-building mechanisms

Complete Flow

import { ethers } from 'ethers';

const API_KEY = process.env.FINTERNET_API_KEY;
const BASE_URL = 'https://api.fmm.finternetlab.io/v1';

async function apiRequest(endpoint: string, options: RequestInit = {}) {
const response = await fetch(`${BASE_URL}${endpoint}`, {
...options,
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
...options.headers,
},
});

if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || 'API request failed');
}

return response.json();
}

// 1. Create payment intent with time-locked release
const createTimeLockedPayment = async (
amount: string,
lockDurationDays: number
) => {
const lockUntil = Math.floor(Date.now() / 1000) + (lockDurationDays * 24 * 60 * 60);

const intent = await apiRequest('/payment-intents', {
method: 'POST',
body: JSON.stringify({
amount,
currency: 'USDC',
type: 'DELIVERY_VS_PAYMENT',
settlementMethod: 'OFF_RAMP_MOCK',
settlementDestination: 'bank_account_123',
metadata: {
releaseType: 'TIME_LOCKED',
timeLockUntil: lockUntil.toString(),
deliveryPeriod: lockDurationDays * 24 * 60 * 60,
},
}),
});

return intent;
};

// 2. Confirm payment (buyer pays)
const confirmPayment = async (intentId: string) => {
const intent = await apiRequest(`/payment-intents/${intentId}`);
const typedData = intent.data.typedData;

const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

const signature = await signer.signTypedData(
typedData.domain,
typedData.types,
typedData.message
);

await apiRequest(`/payment-intents/${intentId}/confirm`, {
method: 'POST',
body: JSON.stringify({
signature,
payerAddress: await signer.getAddress(),
}),
});
};

// 3. Monitor time lock status
const monitorTimeLock = async (intentId: string) => {
const conditionalPayment = await apiRequest(`/payment-intents/${intentId}/conditional-payment`);
const timeLockUntil = parseInt(conditionalPayment.data.timeLockUntil);
const now = Math.floor(Date.now() / 1000);

if (now < timeLockUntil) {
const remaining = timeLockUntil - now;
const days = Math.floor(remaining / 86400);
const hours = Math.floor((remaining % 86400) / 3600);

console.log(`Time lock expires in ${days} days, ${hours} hours`);
return false; // Not yet expired
}

return true; // Expired
};

// 4. Check if funds were released
const checkReleaseStatus = async (intentId: string) => {
const conditionalPayment = await apiRequest(`/payment-intents/${intentId}/conditional-payment`);

if (conditionalPayment.data.releasedAt) {
const releasedAt = new Date(parseInt(conditionalPayment.data.releasedAt) * 1000);
console.log(`Funds released at: ${releasedAt.toISOString()}`);
return true;
}

return false;
};

// Complete example
const runTimeLockedPayment = async () => {
// Create payment with 30-day time lock
const intent = await createTimeLockedPayment('1000.00', 30);
console.log('Payment intent created:', intent.id);

// Confirm payment
await confirmPayment(intent.id);
console.log('Payment confirmed');

// Monitor time lock
const checkInterval = setInterval(async () => {
const expired = await monitorTimeLock(intent.id);

if (expired) {
clearInterval(checkInterval);

// Check if released
const released = await checkReleaseStatus(intent.id);
if (released) {
console.log('Funds automatically released!');
} else {
console.log('Waiting for automatic release...');
}
}
}, 3600000); // Check every hour
};

Python Example

import requests
import os
import time
from datetime import datetime, timedelta

API_KEY = os.environ['FINTERNET_API_KEY']
BASE_URL = 'https://api.fmm.finternetlab.io/v1'

def api_request(endpoint, method='GET', data=None):
url = f'{BASE_URL}{endpoint}'
headers = {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
}

if method == 'POST':
response = requests.post(url, headers=headers, json=data)
else:
response = requests.get(url, headers=headers)

if not response.ok:
error = response.json()
raise Exception(error.get('error', {}).get('message', 'API request failed'))

return response.json()

# Create time-locked payment
def create_time_locked_payment(amount, lock_duration_days):
lock_until = int(time.time()) + (lock_duration_days * 24 * 60 * 60)

intent = api_request('/payment-intents', 'POST', {
'amount': amount,
'currency': 'USDC',
'type': 'DELIVERY_VS_PAYMENT',
'settlementMethod': 'OFF_RAMP_MOCK',
'settlementDestination': 'bank_account_123',
'metadata': {
'releaseType': 'TIME_LOCKED',
'timeLockUntil': str(lock_until),
'deliveryPeriod': lock_duration_days * 24 * 60 * 60,
}
})

return intent

# Monitor time lock
def monitor_time_lock(intent_id):
conditional_payment = api_request(f'/payment-intents/{intent_id}/conditional-payment')
time_lock_until = int(conditional_payment['data']['timeLockUntil'])
now = int(time.time())

if now < time_lock_until:
remaining = time_lock_until - now
days = remaining // 86400
hours = (remaining % 86400) // 3600

print(f'Time lock expires in {days} days, {hours} hours')
return False

return True

# Run example
intent = create_time_locked_payment('1000.00', 30)
print(f'Payment intent created: {intent["id"]}')

# Monitor until release
while True:
if monitor_time_lock(intent["id"]):
conditional_payment = api_request(f'/payment-intents/{intent["id"]}/conditional-payment')
if conditional_payment['data'].get('releasedAt'):
released_at = datetime.fromtimestamp(int(conditional_payment['data']['releasedAt']))
print(f'Funds released at: {released_at}')
break

time.sleep(3600) # Check every hour

Use Cases

Subscription Service

// Monthly subscription with 30-day time lock
const subscription = await createTimeLockedPayment('99.00', 30);
// Funds released after 30 days automatically

Escrow for Services

// Service payment with 7-day time lock for quality assurance
const servicePayment = await createTimeLockedPayment('500.00', 7);
// Funds released after 7 days if no disputes

Delayed Payout

// Delayed payout for contractor
const contractorPayout = await createTimeLockedPayment('2000.00', 14);
// Funds released after 14 days