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

# Finding and Reading Data From the Ledger

> Read parties, ledger end, and active contracts; stream and monitor transaction history; fetch transactions by updateId.

The wallet SDK primarily focus on an on-party basis interaction, therefore it is almost always required to define the party you are using for each command.

## Reading Available Parties

Reading all available parties to you can easily be done using the wallet SDK as shown in the example below, and the result is paginated. It's worth noting that the call to read all available parties doesn't use the the party and synchronizer fields therefore changing them has no effect on the result.

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk'

export default async function () {
    // it is important to configure the SDK correctly else you might run into connectivity or authentication issues
    const sdk = await SDK.create({
        auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT,
        ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL,
    })

    await sdk.party.list()
}
```

## Reading Ledger End

A lot of different requests will take a ledger offset to ensure the requested time correlates with ledger time. A Validator does not have a block height since there is no total state replication. There are two values that correlate:

* ledger time - this is the time the ledger chooses when computing a transaction prior to commit.
* record time - this is the time assigned by the sequencer when registering the confirmation request.

Ledger time should be used for all operations in your local environment (that does not affect partners). When doing reconciliation for transactions with partners or other members of a synchronizer it is better to use record time.

Ledger end is used as a default for wallet SDK operations.

## Reading Active Contracts

Using the above ledger time we can figure out what the current state of all active contracts are. Contracts can be in two states - active and archived - which correlates to the UTXO mode of unspent and spent. Active contracts are contracts that are unspent and thereby can be used in new transactions or to exercise choices.

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk'

export default async function () {
    const sdk = await SDK.create({
        auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT,
        ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL,
    })
    const myParty = global.EXISTING_PARTY_1
    //we use holdings as an example here
    const myTemplateId = '#splice-amulet:Splice.Amulet:Amulet'

    await sdk.ledger.acsReader.read({
        parties: [myParty],
        templateIds: [myTemplateId], //this is optional for if you want to filter by template id
        filterByParty: true,
    })
}
```

## Streaming and Monitoring Transaction History

In order to stream transaction events as they happen on ledger the `listHoldingTransactions` endpoint can be used. This takes two ledger offset and gives an overview of all token standard transactions that have happened between. It also returns a `nextOffset` that can be used when calling the endpoint again. This will allow you to easily ensure you do not receive any transaction twice and you are only querying the transactions that have happened after.

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk'

export default async function () {
    const sdk = await SDK.create({
        auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT,
        ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL,
        token: global.TOKEN_NAMESPACE_CONFIG,
    })
    const myParty = global.EXISTING_PARTY_1

    await sdk.token.holdings({ partyId: myParty })
}
```

to quickly convert the stream into deposit and withdrawal you can use this function:

```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
function convertToTransaction(pt: Transaction, associatedParty: string): object[] {
    return pt.events.flatMap((event) => {
        if (event.label.type === 'TransferIn') {
            return [{
                updateId: pt.updateId,
                recordTime: pt.recordTime,
                from: event.label.sender,
                to: associatedParty,
                amount: Number(event.unlockedHoldingsChangeSummary.amountChange),
                instrumentId: 'Amulet', //hardcoded instrumentId from local net
                fee: Number(event.label.burnAmount),
                memo: event.label.reason,
            }];
        } else if (event.label.type === 'TransferOut') {
            const label = event.label
            return event.label.receiverAmounts.map((receiverAmount: any) => ({
                updateId: pt.updateId,
                recordTime: pt.recordTime,
                from: associatedParty,
                to: receiverAmount.receiver,
                amount: Number(receiverAmount.amount),
                instrumentId: 'Amulet', //hardcoded instrumentId from local net
                fee: Number(label.burnAmount),
                memo: label.meta.reason,
            }));
        } else {
            return [];
        }
    });
}
```

## How do I fetch transaction by updateId?

Given an update Id, the token namespace has a method for getting a transaction based on the updateId. This will print out the transaction in the same format as `sdk.token.holdings`

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { SDK, localNetStaticConfig } from '@canton-network/wallet-sdk'

export default async function () {
    const sdk = await SDK.create({
        auth: global.TOKEN_PROVIDER_CONFIG_DEFAULT,
        ledgerClientUrl: localNetStaticConfig.LOCALNET_APP_USER_LEDGER_URL,
        amulet: global.AMULET_NAMESPACE_CONFIG,
        token: global.TOKEN_NAMESPACE_CONFIG,
    })

    const myParty = global.EXISTING_PARTY_1

    const [amuletTapCommand, amuletTapDisclosedContracts] =
        await sdk.amulet.tap(myParty, '2000')

    const result = await sdk.ledger
        .prepare({
            partyId: myParty,
            commands: amuletTapCommand,
            disclosedContracts: amuletTapDisclosedContracts,
        })
        .sign(global.EXISTING_PARTY_1_KEYS.privateKey)
        .execute({ partyId: myParty })

    await sdk.token.transactionsById({
        updateId: result.updateId,
        partyId: myParty,
    })
}
```
