> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rebelfi.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Walkthrough

> Complete integration walkthrough: onboarding, supply, earnings, and unwind

This guide walks through a complete RebelFi integration — from setup through yield generation and withdrawal. Every step includes working code. The same flow applies whether you're building for an exchange, neobank, payment processor, or any other use case.

## Prerequisites

<Steps>
  <Step title="Create a Wallet Profile">
    Go to **Settings → Wallet Profiles** in the dashboard. Create a profile with the blockchains you need enabled. See [Wallet Profiles](/guides/wallet-profiles) for details.
  </Step>

  <Step title="Generate an API Key">
    Go to **Settings → API Keys**. Generate a key and attach it to your Wallet Profile. Copy the key immediately — it's shown only once.
  </Step>

  <Step title="Install the SDK">
    ```bash theme={null}
    npm install @rebelfi/sdk
    ```
  </Step>
</Steps>

```typescript theme={null}
import { RebelfiClient, RebelfiError, ErrorCode } from '@rebelfi/sdk';

const client = new RebelfiClient({
  apiKey: process.env.REBELFI_API_KEY
});
```

## 1. Register a Wallet

Register the wallet you want to deploy funds from. This is **idempotent** — calling it again with the same address returns the existing wallet.

```typescript theme={null}
const wallet = await client.wallets.register({
  walletAddress: 'So11...abc',
  blockchain: 'solana',
  userId: 'user-123' // optional: link to your internal user ID
});

console.log('Wallet ID:', wallet.walletId);
// Use walletId for all subsequent API calls
```

The optional `userId` field links this wallet to your internal user. You can later query allocations and earnings by `userId` instead of wallet address.

### Update metadata

Attach arbitrary metadata to a wallet:

```typescript theme={null}
await client.wallets.update(wallet.walletId, {
  orgMetadata: { plan: 'premium', kycStatus: 'verified' }
});
```

### List wallets

Query wallets for a user or by blockchain:

```typescript theme={null}
const { wallets, total } = await client.wallets.list({
  userId: 'user-123'
});
console.log(`User has ${total} wallets`);
```

## 2. Discover Venues and Strategies

Find available yield opportunities:

```typescript theme={null}
const { venues, strategyCount } = await client.venues.list({
  blockchain: 'solana',
  token: 'USDC'
});

for (const venue of venues) {
  console.log(`${venue.name} (${venue.protocol})`);
  for (const strategy of venue.strategies) {
    console.log(`  ${strategy.name}: ${(strategy.apy * 100).toFixed(2)}% APY`);
  }
}
```

Pick a strategy to use:

```typescript theme={null}
const venue = venues[0];
const strategy = venue.strategies[0];
```

## 3. Check Pre-Supply Allocations

Before supplying, verify the user's current positions:

```typescript theme={null}
const { allocations, totalValue } = await client.allocations.list({
  walletId: wallet.walletId
});

if (allocations.length === 0) {
  console.log('No existing positions — ready to supply');
} else {
  console.log(`${allocations.length} existing positions, total value: ${totalValue}`);
}
```

## 4. Supply Flow

### Create the operation

```typescript theme={null}
const operation = await client.operations.supply({
  walletId: wallet.walletId,
  strategyId: strategy.strategyId,
  amount: '1000000000', // 1000 USDC (6 decimals)
  tokenAddress: strategy.tokenAddress
});

console.log('Operation:', operation.operationId);
console.log('Status:', operation.status); // 'AWAITING_SIGNATURE'
console.log('Expires:', operation.expiresAt);
```

<Warning>
  Operations expire after a short window. Sign and submit promptly.
</Warning>

### Sign the transaction

The operation contains an unsigned transaction. Have the user sign it:

```typescript theme={null}
import { VersionedTransaction, Connection } from '@solana/web3.js';

const unsignedTxBuffer = Buffer.from(
  operation.transactions[0].unsignedTransaction,
  'base64'
);
const transaction = VersionedTransaction.deserialize(unsignedTxBuffer);

// User signs via their wallet
transaction.sign([userKeypair]);
```

### Broadcast and submit hash

**Option A — You broadcast:**

```typescript theme={null}
const connection = new Connection('https://api.mainnet-beta.solana.com');
const txHash = await connection.sendTransaction(transaction);

await client.transactions.submitHash({
  operationId: operation.operationId,
  txHash
});
```

**Option B — RebelFi broadcasts:**

```typescript theme={null}
const signedTxBase64 = Buffer.from(transaction.serialize()).toString('base64');

await client.transactions.submitSigned({
  operationId: operation.operationId,
  signedTransaction: signedTxBase64
});
```

### Poll for confirmation

```typescript theme={null}
async function waitForConfirmation(operationId: number) {
  const timeout = 60_000;
  const start = Date.now();

  while (Date.now() - start < timeout) {
    const op = await client.operations.get(operationId);

    if (op.status === 'CONFIRMED') return op;
    if (op.status === 'FAILED') {
      throw new Error(op.transactions[0]?.error || 'Operation failed');
    }

    await new Promise(r => setTimeout(r, 2000));
  }
  throw new Error('Timeout');
}

const confirmed = await waitForConfirmation(operation.operationId);
console.log('Supply confirmed!');
```

## 5. Identifier Equivalence

After supply, you can query allocations and earnings using any wallet identifier — they all return the same data:

```typescript theme={null}
// All three return identical results:
const byId = await client.allocations.list({ walletId: wallet.walletId });
const byAddr = await client.allocations.list({ walletAddress: 'So11...abc' });
const byUser = await client.allocations.list({ userId: 'user-123' });
```

The same applies to the `get` and `earnings` methods. Use whichever identifier is most convenient.

## 6. Monitor Yield

### Check allocations

```typescript theme={null}
const { allocations } = await client.allocations.list({
  walletId: wallet.walletId
});

for (const alloc of allocations) {
  console.log(`${alloc.venueName} — ${alloc.strategyName}`);
  console.log(`  Principal: ${alloc.principal}`);
  console.log(`  Current value: ${alloc.currentValue}`);
  console.log(`  Yield earned: ${alloc.yieldEarned}`);
}
```

### Get earnings history

```typescript theme={null}
const earnings = await client.allocations.earnings({
  walletId: wallet.walletId,
  blockchain: 'solana',
  token: 'USDC',
  days: 30,
  includeBreakdown: true
});

console.log(`Total yield: ${earnings.totalYieldEarned}`);

for (const day of earnings.history) {
  console.log(`${day.date}: +${day.yieldEarned} (cumulative: ${day.cumulativeYield})`);
}
```

## 7. Unwind (Withdraw)

When the user wants to withdraw, create an unwind operation:

```typescript theme={null}
// Partial withdrawal
const unwind = await client.operations.unwind({
  walletId: wallet.walletId,
  strategyId: strategy.strategyId,
  amount: '500000000' // 500 USDC
});

// Sign and submit (same flow as supply)
const unsignedTx = Buffer.from(unwind.transactions[0].unsignedTransaction, 'base64');
const tx = VersionedTransaction.deserialize(unsignedTx);
tx.sign([userKeypair]);

const signedBase64 = Buffer.from(tx.serialize()).toString('base64');
await client.transactions.submitSigned({
  operationId: unwind.operationId,
  signedTransaction: signedBase64
});

await waitForConfirmation(unwind.operationId);
console.log('Withdrawal complete');
```

## 8. Cancel Flow

Cancel a pending operation that hasn't been submitted:

```typescript theme={null}
const result = await client.operations.cancel(operation.operationId);
console.log(result.status); // 'CANCELLED'
```

<Tip>
  You rarely need to cancel manually. Creating a new operation for the same wallet **automatically cancels** any pending ones.
</Tip>

## 9. Error Handling

```typescript theme={null}
import { RebelfiError, ErrorCode } from '@rebelfi/sdk';

try {
  await client.operations.supply(request);
} catch (error) {
  if (!(error instanceof RebelfiError)) throw error;

  if (error.is(ErrorCode.INSUFFICIENT_BALANCE)) {
    console.error('Available:', error.details?.available);
  } else if (error.is(ErrorCode.WALLET_NOT_FOUND)) {
    console.error('Register the wallet first');
  } else if (error.is(ErrorCode.OPERATION_IN_PROGRESS)) {
    console.error('Wait for current operation to complete');
  } else {
    console.error(`${error.code}: ${error.message}`);
  }
}
```

See the [Error Handling guide](/sdk/error-handling) for comprehensive patterns including retry logic.

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Handling" icon="triangle-exclamation" href="/sdk/error-handling">
    Comprehensive error handling patterns
  </Card>

  <Card title="TypeScript Reference" icon="brackets-curly" href="/sdk/reference/client">
    Complete type definitions
  </Card>
</CardGroup>
