Skip to main content

Workflows

Workflows are asynchronous, multi-step processes that track the progress of loan operations.

What is a Workflow?

A workflow represents a complex operation (like borrowing or repaying) that involves multiple steps and external events (like Bitcoin deposits).
const result = await sdk.getLoan({
  collateralBTC: 0.1,
  loanAmountUSD: 5000,
  onStatusUpdate: (status) => {
    console.log(`Step ${status.step}: ${status.label}`);
  }
});

console.log('Workflow ID:', result.workflowId);

Workflow Types

Borrow Workflow

Tracks the loan creation process:
StageDescription
INITIALIZINGWorkflow starting
DEPOSIT_ADDRESS_READYDeposit address generated
AWAITING_DEPOSITWaiting for BTC deposit
DEPOSIT_CONFIRMEDDeposit received
COLLATERAL_DEPOSITEDCollateral processed
PREPARING_LOANLoan being prepared
LOAN_CONFIRMEDLoan executed
COMPLETEDWorkflow complete
FAILEDWorkflow failed

Repay Workflow

Tracks the repayment process:
StageDescription
INITIALIZINGStarting repayment
TRANSFERRING_TO_KERNELMoving funds
REPAYING_LOANExecuting repayment
WITHDRAWING_COLLATERALWithdrawing BTC
TRANSFERRING_TO_PLATFORM_WALLETPreparing bridge
BRIDGE_INITIALIZINGBridge starting
BRIDGE_QUOTE_READYBridge quote received
BRIDGE_SWAP_CREATEDSwap created
BRIDGE_EXECUTING_APPROVALApproving tokens
BRIDGE_APPROVAL_CONFIRMEDApproval confirmed
BRIDGE_EXECUTING_INITIATEInitiating bridge
BRIDGE_INITIATE_CONFIRMEDBridge initiated
BRIDGE_AWAITING_BRIDGE_COMPLETIONWaiting for bridge
BRIDGE_COMPLETEDBridge complete
COMPLETEDWorkflow complete
FAILEDWorkflow failed

Workflow Status Object

interface WorkflowStatus {
  stage: string;           // Current stage name
  step: number;            // Step number (1-based)
  label: string;           // Human-readable label
  description: string;     // Detailed description
  depositAddress?: string; // BTC deposit address (if applicable)
  depositAmount?: number;  // Required deposit in satoshis
  error?: string;          // Error message (if failed)
  isComplete: boolean;     // Whether workflow is done
  isFailed: boolean;       // Whether workflow failed
  rawData: any;            // Raw API response
}

Tracking Workflows

Automatic Tracking

By default, workflows are tracked automatically:
const sdk = new BorrowSDK({
  // ...
  autoTrackWorkflows: true // Default
});

await sdk.getLoan({
  collateralBTC: 0.1,
  loanAmountUSD: 5000,
  onStatusUpdate: (status) => console.log(status.label),
  onComplete: () => console.log('Done!')
});

Manual Tracking

Disable auto-tracking and track manually:
const sdk = new BorrowSDK({
  // ...
  autoTrackWorkflows: false
});

const workflowId = await sdk.executeBorrow(quote);

// Track manually
await sdk.trackWorkflow(workflowId, {
  onStatusUpdate: (status) => console.log(status),
  onComplete: () => console.log('Complete'),
  onError: (error) => console.error(error)
}, 'borrow');

Resuming Tracking

Resume tracking a workflow that was interrupted:
// Store workflow ID somewhere
localStorage.setItem('pendingWorkflow', result.workflowId);

// Later, resume tracking
const workflowId = localStorage.getItem('pendingWorkflow');
if (workflowId) {
  await sdk.resumeLoan(workflowId, {
    onStatusUpdate: (status) => console.log(status),
    onComplete: () => {
      localStorage.removeItem('pendingWorkflow');
    }
  });
}

Workflow Callbacks

onStatusUpdate

Called when the workflow stage changes:
onStatusUpdate: (status: WorkflowStatus) => {
  console.log(`[${status.step}] ${status.label}`);
  console.log(`  ${status.description}`);

  // Update UI progress
  updateProgressBar(status.step, getTotalSteps(status.stage));
}

onDepositReady

Called when a deposit address is ready (borrow workflows):
onDepositReady: (info: DepositInfo) => {
  console.log('Deposit Required:');
  console.log(`  Address: ${info.address}`);
  console.log(`  Amount: ${info.amountBTC} BTC`);
  console.log(`  Satoshis: ${info.amount}`);

  // Show QR code, send notification, etc.
  showDepositModal(info);
}

onComplete

Called when the workflow completes successfully:
onComplete: (result: any) => {
  console.log('Workflow completed!');
  console.log('Result:', result);

  // Navigate to success page, show notification, etc.
  router.push('/loan/success');
}

onError

Called when the workflow fails:
onError: (error: string) => {
  console.error('Workflow failed:', error);

  // Show error message, offer retry, etc.
  showErrorModal(error);
}

Polling Configuration

The SDK polls for workflow status at a configurable interval:
const sdk = new BorrowSDK({
  // ...
  workflowPollInterval: 2000 // Poll every 2 seconds (default)
});
IntervalUse Case
1000msResponsive UI, more API calls
2000msDefault, good balance
5000msLess frequent updates, fewer API calls
Minimum interval is 100ms.

Stopping Tracking

Stop Specific Workflow

const result = await sdk.getLoan({ ... });

// Later, stop tracking
result.stop();

Stop All Tracking

// Stops all active workflow trackers
sdk.clearSession();

Workflow State Diagram

Borrow Workflow

Getting Workflow Status Manually

// Get current status without callbacks
const status = await sdk.getStatus(workflowId);

console.log('Stage:', status.stage);
console.log('Complete:', status.isComplete);

Handling Pending Workflows

Check for and resume pending workflows on app load:
async function checkPendingWorkflows(sdk: BorrowSDK) {
  const pending = await sdk.getPendingLoans();

  for (const loan of pending) {
    const workflowId = loan.borrowTransaction?.workflowId;
    if (workflowId) {
      console.log(`Found pending loan: ${workflowId}`);

      await sdk.resumeLoan(workflowId, {
        onStatusUpdate: (s) => console.log(s.label),
        onComplete: () => console.log('Resumed loan completed'),
        onDepositReady: (info) => {
          console.log(`Still waiting for deposit to ${info.address}`);
        }
      });
    }
  }
}

Best Practices

1. Always Handle Errors

await sdk.getLoan({
  // ...
  onError: (error) => {
    // Log for debugging
    console.error('Workflow error:', error);

    // Show user-friendly message
    showNotification('Loan failed. Please try again.');

    // Track for analytics
    analytics.track('loan_failed', { error });
  }
});

2. Persist Workflow IDs

const result = await sdk.getLoan({ ... });

// Persist for resumption
await saveWorkflowId(result.workflowId);

// On completion, clean up
onComplete: async () => {
  await clearWorkflowId(result.workflowId);
}

3. Show Progress Indicator

const stages = ['INITIALIZING', 'AWAITING_DEPOSIT', 'PROCESSING', 'COMPLETED'];

onStatusUpdate: (status) => {
  const index = stages.indexOf(status.stage);
  const progress = (index / stages.length) * 100;
  updateProgressBar(progress);
}

4. Handle Page Refresh

// On page load
useEffect(() => {
  const pendingId = localStorage.getItem('workflowId');
  if (pendingId) {
    sdk.resumeLoan(pendingId, callbacks);
  }
}, []);