> ## Documentation Index
> Fetch the complete documentation index at: https://base-a060aa97-fix-dead-service-links.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# dataSuffix

> Append arbitrary data to transaction calldata for attribution tracking

export const Button = ({children, disabled, variant = "primary", size = "medium", iconName, roundedFull = false, className = '', fullWidth = false, onClick = undefined}) => {
  const variantStyles = {
    primary: 'bg-blue text-black border border-blue hover:bg-blue-80 active:bg-[#06318E] dark:text-white',
    secondary: 'bg-white border border-white text-palette-foreground hover:bg-zinc-15 active:bg-zinc-30',
    outlined: 'bg-transparent text-white border border-white hover:bg-white hover:text-black active:bg-[#E3E7E9]'
  };
  const sizeStyles = {
    medium: 'text-md px-4 py-2 gap-3',
    large: 'text-lg px-6 py-4 gap-5'
  };
  const sizeIconRatio = {
    medium: '0.75rem',
    large: '1rem'
  };
  const classes = ['text-md px-4 py-2 whitespace-nowrap', 'flex items-center justify-center', 'disabled:opacity-40 disabled:pointer-events-none', 'transition-all', variantStyles[variant], sizeStyles[size], roundedFull ? 'rounded-full' : 'rounded-lg', fullWidth ? 'w-full' : 'w-auto', className];
  const buttonClasses = classes.filter(Boolean).join(' ');
  const iconSize = sizeIconRatio[size];
  return <button type="button" disabled={disabled} className={buttonClasses} onClick={onClick}>
      <span>{children}</span>
      {iconName && <Icon name={iconName} width={iconSize} height={iconSize} color="currentColor" />}
    </button>;
};

export const BaseBanner = ({content = null, id, dismissable = true}) => {
  const LOCAL_STORAGE_KEY_PREFIX = 'cb-docs-banner';
  const [isVisible, setIsVisible] = useState(false);
  const onDismiss = () => {
    localStorage.setItem(`${LOCAL_STORAGE_KEY_PREFIX}-${id}`, 'false');
    setIsVisible(false);
  };
  useEffect(() => {
    const storedValue = localStorage.getItem(`${LOCAL_STORAGE_KEY_PREFIX}-${id}`);
    setIsVisible(storedValue !== 'false');
  }, []);
  if (!isVisible) {
    return null;
  }
  return <div className="fixed bottom-0 left-0 right-0 bg-white py-8 px-4 lg:px-12 z-50 text-black dark:bg-black dark:text-white border-t dark:border-gray-95">
      <div className="flex items-center max-w-8xl mx-auto">
        {typeof content === 'function' ? content({
    onDismiss
  }) : content}
        {dismissable && <button onClick={onDismiss} className="flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors" aria-label="Dismiss banner">
          ✕
        </button>}
      </div>
    </div>;
};

Defined in [ERC-8021](https://eip.tools/eip/8021)

<Info>
  The dataSuffix capability allows apps to append arbitrary hex-encoded bytes to transaction calldata. This enables attribution tracking, allowing platforms to identify which app originated a transaction and distribute rewards accordingly.
</Info>

## Parameters

<ParamField body="value" type="`0x${string}`" required>
  Hex-encoded bytes to append to the transaction calldata. This value is appended to the end of the calldata for each call in the batch.
</ParamField>

<ParamField body="optional" type="boolean">
  When `true`, the wallet may ignore the capability if it doesn't support it. When `false` or omitted, the wallet must support the capability or reject the request.
</ParamField>

## Returns

<ResponseField name="dataSuffix" type="object">
  The data suffix capability configuration for the specified chain.

  <Expandable title="DataSuffix capability properties">
    <ResponseField name="supported" type="boolean">
      Indicates whether the wallet supports appending data suffixes to transaction calldata.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example Usage

<RequestExample>
  ```typescript Check DataSuffix Support theme={null}
  const capabilities = await provider.request({
    method: 'wallet_getCapabilities',
    params: [userAddress]
  });

  const dataSuffixSupport = capabilities["0x2105"]?.dataSuffix;
  ```

  ```typescript Send Transaction with DataSuffix theme={null}
  const result = await provider.request({
    method: "wallet_sendCalls",
    params: [{
      version: "1.0",
      chainId: "0x2105",
      from: userAddress,
      calls: [{
        to: "0x1234567890123456789012345678901234567890",
        value: "0x0",
        data: "0xa9059cbb000000000000000000000000..."
      }],
      capabilities: {
        dataSuffix: {
          value: "0x1234567890abcdef1234567890abcdef",
          optional: true
        }
      }
    }]
  });
  ```
</RequestExample>

<ResponseExample>
  ```json Capability Response (Supported) theme={null}
  {
    "0x2105": {
      "dataSuffix": {
        "supported": true
      }
    }
  }
  ```

  ```json Capability Response (Unsupported) theme={null}
  {
    "0x2105": {
      "dataSuffix": {
        "supported": false
      }
    }
  }
  ```
</ResponseExample>

## Error Handling

| Code | Message                        | Description                                                   |
| ---- | ------------------------------ | ------------------------------------------------------------- |
| 4100 | Data suffix not supported      | Wallet does not support data suffix functionality             |
| 5700 | DataSuffix capability required | Transaction requires dataSuffix but wallet doesn't support it |

## How It Works

When a wallet receives a `dataSuffix` capability, the suffix is appended to `userOp.callData`. The suffix bytes are concatenated directly to the end of the calldata, making them available for onchain parsing and attribution.

## Use Cases

### Builder Codes Attribution

The primary use case for `dataSuffix` is [Builder Codes](/apps/builder-codes/builder-codes) attribution. Builder Codes are unique identifiers that allow apps to receive attribution for onchain activity they generate.

```typescript theme={null}
import { Attribution } from "ox/erc8021";

// Example: Using Builder Code with dataSuffix.
// Using the ox/erc8021 package to generate the ERC-8021 suffix from your builder code.
const builderCodeSuffix = Attribution.toDataSuffix({
  codes: ['bc_foobar'], // Get your code from base.dev
});

await provider.request({
  method: "wallet_sendCalls",
  params: [{
    version: "1.0",
    chainId: "0x2105",
    from: userAddress,
    calls: [{
      to: contractAddress,
      value: "0x0",
      data: swapCallData
    }],
    capabilities: {
      dataSuffix: {
        value: builderCodeSuffix,
        optional: true
      }
    }
  }]
});
```

Register on [base.dev](https://base.dev) to get your Builder Code for proper attribution.

## Best Practices

1. **Use with Builder Codes**: Register on [base.dev](https://base.dev) to get your Builder Code for proper attribution
2. **Set optional appropriately**: Use `optional: true` if your app can function without attribution tracking
3. **Keep suffixes small**: Larger suffixes increase gas costs

<Info>
  For wallet developers implementing dataSuffix support, see the [For Wallet Developers](/apps/builder-codes/builder-codes#for-wallet-developers) section in the Builder Codes guide.
</Info>

## Related Capabilities

* [paymasterService](/base-account/reference/core/capabilities/paymasterService) - Combine with sponsored transactions
* [atomic](/base-account/reference/core/capabilities/atomic) - Use with atomic batch transactions

<BaseBanner
  id="privacy-policy"
  dismissable={false}
  content={({ onDismiss }) => (
<div className="flex items-center">
  <div className="mr-2">
    We're updating the Base Privacy Policy, effective July 25, 2025, to reflect an expansion of Base services. Please review the updated policy here:{" "}
    <a
      href="https://docs.base.org/privacy-policy-2025"
      target="_blank"
      className="whitespace-nowrap"
    >
      Base Privacy Policy
    </a>. By continuing to use Base services, you confirm that you have read and understand the updated policy.
  </div>
  <Button onClick={onDismiss}>I Acknowledge</Button>
</div>
)}
/>
