# Examples

Full end-to-end examples showing how to configure and complete claims.

## Claim Configuration

A claim is defined by an `iClaimBuilderDoc`. Each plugin in the `plugins` array has this shape:

```typescript
interface IntegrationPluginParams<T extends ClaimIntegrationPluginType> {
  instanceId: string;       // Unique ID for this plugin instance within the claim
  pluginId: T;              // Plugin type: "numUses", "codes", "password", etc.
  version: string;          // Plugin version (usually "0")
  publicParams: object;     // Plugin-specific config (visible to users)
  privateParams: object;    // Plugin-specific secrets (hidden from users)
}
```

## Example: Code-Gated Claim

A claim where users redeem one-time codes. Limited to 100 claims total.

```typescript
import crypto from 'crypto';
import CryptoJS from 'crypto-js';

const seedCode = crypto.randomBytes(32).toString('hex');
const numCodes = 100;

// Generate codes from seed
const codes = [];
for (let i = 0; i < numCodes; i++) {
  const hash = CryptoJS.SHA256(`${seedCode}-${i}`).toString();
  codes.push(`${hash}-${i}`);
}

const claim: iClaimBuilderDoc = {
  plugins: [
    {
      pluginId: 'numUses',
      instanceId: 'num-uses-instance',
      version: '0',
      publicParams: { maxUses: 100 },
      privateParams: {}
    },
    {
      pluginId: 'codes',
      instanceId: 'codes-instance',
      version: '0',
      publicParams: { numCodes: 100 },
      privateParams: { codes, seedCode }
    }
  ],
  state: {},
  action: { seedCode },
  // ... other required fields (collectionId, createdBy, etc.)
};
```

**Completing this claim:**

```typescript
const res = await BitBadgesApi.completeClaim(claimId, 'bb1...', {
  _expectedVersion: '0',
  'codes-instance': { code: codes[0] }  // Keyed by instanceId
});

// Check status after ~2 seconds
const status = await BitBadgesApi.getClaimAttemptStatus(res.claimAttemptId);
```

## Example: Password-Gated Auto-Completion

A backend-driven claim where your server completes claims on behalf of users. No sign-in required — gated by a password only your backend knows.

```typescript
const claim: iClaimBuilderDoc = {
  plugins: [
    {
      pluginId: 'numUses',
      instanceId: 'num-uses',
      version: '0',
      publicParams: { maxUses: 1000, displayAsUnlimited: true },
      privateParams: {}
    },
    {
      pluginId: 'password',
      instanceId: 'backend-password',
      version: '0',
      publicParams: {},
      privateParams: { password: 'my-backend-secret-password' }
    }
  ],
  state: {},
  action: {},
  approach: 'api',
  // ... other required fields
};
```

**Auto-completing from your backend:**

```typescript
// Your backend completes the claim on behalf of the user
await BitBadgesApi.completeClaim(claimId, userAddress, {
  _expectedVersion: '0',
  'backend-password': { password: 'my-backend-secret-password' }
});
```

## Example: Whitelist + Token Ownership (AND Logic)

User must be on a whitelist AND own a specific badge. Both plugins must pass (default AND logic).

```typescript
const claim: iClaimBuilderDoc = {
  plugins: [
    {
      pluginId: 'numUses',
      instanceId: 'num-uses',
      version: '0',
      publicParams: { maxUses: 500 },
      privateParams: {}
    },
    {
      pluginId: 'initiatedBy',
      instanceId: 'sign-in',
      version: '0',
      publicParams: {},
      privateParams: {}
    },
    {
      pluginId: 'whitelist',
      instanceId: 'vip-list',
      version: '0',
      publicParams: { maxUsesPerAddress: 1 },
      privateParams: {
        list: {
          listId: '',
          addresses: ['bb1abc...', 'bb1def...', 'bb1ghi...'],
          whitelist: true
        }
      }
    },
    {
      pluginId: 'must-own-badges',
      instanceId: 'badge-gate',
      version: '0',
      publicParams: {},
      privateParams: {
        ownershipRequirements: {
          $and: [{
            assets: [{
              collectionId: '1',
              assetIds: [{ start: '1', end: '1' }],
              ownershipTimes: [{ start: '1', end: 'MAX' }],
              mustOwnAmounts: { start: '1', end: 'MAX' }
            }]
          }]
        }
      }
    }
  ],
  state: {},
  action: {},
  // ... other required fields
};
```

## Example: OR Logic with Multiple Paths

User can claim by entering a code OR by being on the whitelist. Uses `satisfyMethod` for OR logic. Note `numUses` is always required regardless of success logic.

```typescript
const claim: iClaimBuilderDoc = {
  plugins: [
    {
      pluginId: 'numUses',
      instanceId: 'num-uses',
      version: '0',
      publicParams: { maxUses: 200 },
      privateParams: {}
    },
    {
      pluginId: 'codes',
      instanceId: 'codes-path',
      version: '0',
      publicParams: { numCodes: 100 },
      privateParams: { codes: [...], seedCode: '...' }
    },
    {
      pluginId: 'whitelist',
      instanceId: 'whitelist-path',
      version: '0',
      publicParams: { maxUsesPerAddress: 1 },
      privateParams: {
        useDynamicStore: true,
        dynamicDataId: 'my-store-id',
        dataSecret: 'my-store-secret'
      }
    }
  ],
  satisfyMethod: {
    type: 'OR',
    conditions: ['codes-path', 'whitelist-path']
    // numUses is always required and not included in OR conditions
  },
  state: {},
  action: {},
  // ... other required fields
};
```

**Completing via the code path:**

```typescript
await BitBadgesApi.completeClaim(claimId, 'bb1...', {
  _expectedVersion: '0',
  _specificInstanceIds: ['codes-path'],  // Only attempt the code path
  'codes-path': { code: 'abc-123' }
});
```

## Example: Time-Windowed Claim

Only claimable during a specific time window.

```typescript
const claim: iClaimBuilderDoc = {
  plugins: [
    {
      pluginId: 'numUses',
      instanceId: 'num-uses',
      version: '0',
      publicParams: { maxUses: 50 },
      privateParams: {}
    },
    {
      pluginId: 'transferTimes',
      instanceId: 'time-window',
      version: '0',
      publicParams: {
        transferTimes: [{
          start: '1741564800000',  // March 10, 2025 00:00 UTC
          end: '1742169600000'     // March 17, 2025 00:00 UTC
        }]
      },
      privateParams: {}
    },
    {
      pluginId: 'initiatedBy',
      instanceId: 'sign-in',
      version: '0',
      publicParams: {},
      privateParams: {}
    }
  ],
  state: {},
  action: {},
  // ... other required fields
};
```

## Simulating Before Completing

Always simulate first to check if a claim would succeed:

```typescript
// Simulate (instant, no side effects)
const sim = await BitBadgesApi.simulateClaim(claimId, 'bb1...', {
  _expectedVersion: '0',
  'codes-instance': { code: 'abc-123' }
});

// If simulation passes, complete for real
const res = await BitBadgesApi.completeClaim(claimId, 'bb1...', {
  _expectedVersion: '0',
  'codes-instance': { code: 'abc-123' }
});
```

## Verifying Claim Success

```typescript
// Check if an address has claimed
const result = await BitBadgesApi.checkClaimSuccess(claimId, 'bb1...');
if (result.successCount >= 1) {
  // Grant access, show content, etc.
}

// Check a specific attempt
const status = await BitBadgesApi.getClaimAttemptStatus(claimAttemptId);
if (status.success) {
  // This attempt succeeded
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bitbadges.io/for-developers/claims/examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
