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

# Preparing data

This guide covers how to compute currency conversions for holdings and transactions and structure the resulting data into a format ready for asynchronous document generation.

## Interpret the rates

The `rates` object uses `{asset}-USD` keys — each representing the price of 1 unit of the asset in USD. When the denomination is not USD, a `USD-{denomination}` key is also included:

```json theme={null}
{
  "BTC-USD": "68106.26",
  "ETH-USD": "2094.45",
  "USD-GBP": "0.75629"
}
```

`"BTC-USD": "68106.26"` means 1 BTC = 68106.26 USD. Multiply by `USD-GBP` to get the GBP value.

Portfolio rates reflect the end of the requested period. Transaction rates are captured at the time the transaction settled.

Assets already held in the denomination currency (e.g. GBP when denomination is GBP) have no rate entry — their value is their amount directly.

For a detailed explanation of how denomination works in this API, see [Denomination](/rest-apis/core-api/concepts#denomination) in the Core API concepts.

## Calculate portfolio values

For each holding, convert the asset's USD rate by the `USD-{denomination}` rate:

```
0.02 BTC × 68106.26 USD/BTC × 0.75629 GBP/USD = 1030.16 GBP
0.5  ETH × 2094.45  USD/ETH × 0.75629 GBP/USD =  792.01 GBP
250.00 GBP                                     =  250.00 GBP  (no rate needed)
```

In code:

```javascript theme={null}
function convertToDenomination(amount, asset, rates, denomination) {
  if (asset === denomination) return parseFloat(amount);
  if (asset === 'USD') return parseFloat(amount) * parseFloat(rates[`USD-${denomination}`]);
  const usdRate = rates[`${asset}-USD`];
  if (denomination === 'USD') return parseFloat(amount) * parseFloat(usdRate);
  return parseFloat(amount) * parseFloat(usdRate) * parseFloat(rates[`USD-${denomination}`]);
}

function computeHoldingValue(holding, rates, denomination) {
  return convertToDenomination(holding.total, holding.asset, rates, denomination).toFixed(2);
}
```

## Calculate transaction values

Each transaction entry has a `denomination` field — the amount and currency the transaction was quoted in, used as the authoritative reference value for compliance purposes — and a `rates` object scoped to that transaction.

To get the GBP value of a transaction, convert the denomination amount using the per-transaction rate:

```javascript theme={null}
function computeTransactionValue(entry, denomination) {
  const { transaction, rates } = entry;
  const { amount, asset } = transaction.denomination;
  return convertToDenomination(amount, asset, rates, denomination).toFixed(2);
}
```

For the GBP→BTC transaction from the previous step, `denomination.asset` is already `GBP`, so the GBP value is `100.00` directly — no rate lookup required.

## Build the payload

Use the helpers above to transform the raw API response into a flat object ready for the report renderer:

```javascript theme={null}
function processStatementData({ portfolio, transactions, denomination }) {
  // Holdings
  const holdings = portfolio.holdings.map(holding => ({
    asset: holding.asset,
    amount: holding.total,
    value: computeHoldingValue(holding, portfolio.rates, denomination)
  }));

  const totalValue = holdings
    .reduce((sum, h) => sum + parseFloat(h.value), 0)
    .toFixed(2);

  // Transactions
  const processedTransactions = transactions.map(entry => {
    const { transaction, rates } = entry;

    const txFees = (transaction.fees ?? [])
      .reduce((sum, fee) => sum + convertToDenomination(fee.amount, fee.asset, rates, denomination), 0)
      .toFixed(2);

    return {
      date: transaction.completedAt.slice(0, 10),
      id: transaction.id,
      status: transaction.status,
      origin: { amount: transaction.origin.amount, asset: transaction.origin.asset },
      destination: { amount: transaction.destination.amount, asset: transaction.destination.asset },
      denominatedAmount: transaction.denomination.amount,
      denominatedAsset: transaction.denomination.asset,
      value: computeTransactionValue(entry, denomination),
      fees: transaction.fees ?? [],
      txFees
    };
  });

  const totalFees = processedTransactions
    .reduce((sum, t) => sum + parseFloat(t.txFees), 0)
    .toFixed(2);

  return {
    period: portfolio.period,
    denomination,
    holdings,
    totalValue,
    transactions: processedTransactions,
    totalFees
  };
}
```

Applied to the GBP example data from the previous step, this produces:

```json theme={null}
{
  "period": {
    "from": "2025-03-01T00:00:00.000Z",
    "to": "2025-03-31T23:59:59.999Z"
  },
  "denomination": "GBP",
  "holdings": [
    { "asset": "BTC", "amount": "0.02", "value": "1030.16" },
    { "asset": "ETH", "amount": "0.5", "value": "792.01" },
    { "asset": "GBP", "amount": "250.00", "value": "250.00" }
  ],
  "totalValue": "2072.17",
  "transactions": [
    {
      "date": "2025-03-23",
      "id": "8daa6dbd-21a0-4305-93c3-bd1d04bc575c",
      "status": "completed",
      "origin": { "amount": "100", "asset": "GBP" },
      "destination": { "amount": "0.00186036", "asset": "BTC" },
      "denominatedAmount": "100",
      "denominatedAsset": "GBP",
      "value": "100.00",
      "fees": [{ "amount": "0.5", "asset": "GBP", "type": "deposit" }],
      "txFees": "0.50"
    }
  ],
  "totalFees": "0.50"
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="Generating report" icon="file-lines" href="/developer-guides/statements/generating-report">
    Build a PDF from the processed data and run the generation pipeline in a background worker.
  </Card>
</CardGroup>
