Bridge Crypto Return Policies
Overview
typescript
type ReturnStrategy = 'manual' | 'automatic' | 'customer_choice'; type Blockchain = 'ethereum' | 'solana' | 'polygon' | 'base' | 'arbitrum' | 'tron'; type Currency = 'usdc' | 'usdb' | 'usdt';
Crypto Return Policy Structure
typescript
interface CryptoReturnPolicy {
id: string;
developer_id: string;
refund_destination_address: string;
refund_destination_blockchain_memo?: string;
refund_destination_chain: Blockchain;
refund_destination_currency: Currency;
strategy: ReturnStrategy;
}
interface CreateReturnPolicyRequest {
refund_destination_address: string;
refund_destination_chain: Blockchain;
refund_destination_currency: Currency;
refund_destination_blockchain_memo?: string;
strategy: ReturnStrategy;
}
Create Return Policy
typescript
async function createReturnPolicy(
request: CreateReturnPolicyRequest
): Promise<CryptoReturnPolicy> {
const response = await fetch(`${BRIDGE_API_URL}/crypto_return_policies`, {
method: 'POST',
headers: {
'Api-Key': API_KEY,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to create return policy: ${error.message}`);
}
return response.json();
}
// Example: Set up return to Ethereum USDC
async function setupETHReturnPolicy(
refundAddress: string,
strategy: ReturnStrategy = 'automatic'
): Promise<CryptoReturnPolicy> {
return createReturnPolicy({
refund_destination_address: refundAddress,
refund_destination_chain: 'ethereum',
refund_destination_currency: 'usdc',
strategy,
});
}
// Example: Set up return with memo (for Tron/Stellar)
async function setupTRONReturnPolicy(
refundAddress: string,
memo: string
): Promise<CryptoReturnPolicy> {
return createReturnPolicy({
refund_destination_address: refundAddress,
refund_destination_chain: 'tron',
refund_destination_currency: 'usdt',
strategy: 'automatic',
refund_destination_blockchain_memo: memo,
});
}
List Return Policies
typescript
async function listReturnPolicies(): Promise<CryptoReturnPolicy[]> {
const response = await fetch(`${BRIDGE_API_URL}/crypto_return_policies`, {
headers: { 'Api-Key': API_KEY },
});
if (!response.ok) {
throw new Error('Failed to list return policies');
}
return response.json();
}
// Get active policy
async function getActivePolicy(): Promise<CryptoReturnPolicy | null> {
const policies = await listReturnPolicies();
return policies[0] || null;
}
Update Return Policy
typescript
async function updateReturnPolicy(
policyId: string,
updates: Partial<CreateReturnPolicyRequest>
): Promise<CryptoReturnPolicy> {
const response = await fetch(`${BRIDGE_API_URL}/crypto_return_policies/${policyId}`, {
method: 'PUT',
headers: {
'Api-Key': API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(updates),
});
if (!response.ok) {
throw new Error('Failed to update return policy');
}
return response.json();
}
// Usage: Update refund address
async function updateRefundAddress(
policyId: string,
newAddress: string
): Promise<CryptoReturnPolicy> {
return updateReturnPolicy(policyId, {
refund_destination_address: newAddress,
});
}
Delete Return Policy
typescript
async function deleteReturnPolicy(policyId: string): Promise<void> {
const response = await fetch(
`${BRIDGE_API_URL}/crypto_return_policies/${policyId}`,
{
method: 'DELETE',
headers: { 'Api-Key': API_KEY },
}
);
if (!response.ok) {
throw new Error('Failed to delete return policy');
}
}
Return Policy Manager
typescript
class ReturnPolicyManager {
async createOrUpdate(
chain: Blockchain,
currency: Currency,
address: string,
memo?: string,
strategy: ReturnStrategy = 'automatic'
): Promise<CryptoReturnPolicy> {
const existing = await this.getActivePolicy();
if (existing) {
return updateReturnPolicy(existing.id, {
refund_destination_address: address,
refund_destination_chain: chain,
refund_destination_currency: currency,
refund_destination_blockchain_memo: memo,
strategy,
});
}
return createReturnPolicy({
refund_destination_address: address,
refund_destination_chain: chain,
refund_destination_currency: currency,
refund_destination_blockchain_memo: memo,
strategy,
});
}
async getActivePolicy(): Promise<CryptoReturnPolicy | null> {
const policies = await listReturnPolicies();
return policies.find(p => p.strategy !== 'disabled') || null;
}
async disablePolicy(policyId: string): Promise<void> {
await deleteReturnPolicy(policyId);
}
}
Handling Failed Transfers
typescript
interface FailedTransferEvent {
transfer_id: string;
original_amount: string;
currency: Currency;
failure_reason: string;
return_policy_id: string;
status: 'pending_return' | 'returned' | 'manual_required';
}
async function handleFailedTransfer(
transferId: string
): Promise<FailedTransferEvent> {
const transfer = await getTransfer(transferId);
if (transfer.state !== 'failed') {
throw new Error('Transfer is not in failed state');
}
const policy = await new ReturnPolicyManager().getActivePolicy();
if (!policy) {
return {
transfer_id: transferId,
original_amount: transfer.amount,
currency: transfer.source.currency as Currency,
failure_reason: 'Insufficient funds or invalid address',
return_policy_id: '',
status: 'manual_required',
};
}
return {
transfer_id: transferId,
original_amount: transfer.amount,
currency: transfer.source.currency as Currency,
failure_reason: 'Transfer failed - initiating return',
return_policy_id: policy.id,
status: 'pending_return',
};
}
Best Practices
- •Always configure - Set up return policy before processing transfers
- •Multiple chains - Support returns on different chains
- •Memo handling - Include memos for Tron/Stellar
- •Monitoring - Track pending returns via webhooks
- •Compliance - Follow KYC requirements for returns