# Read Client

The `PreAuthorizedDebitReadClient` component of the SDK is outlined in the interface found in our [Github repo](https://github.com/seabed-labs/pre-authorized-debit/blob/main/sdk/pre-authorized-debit-v1/src/read/interface/index.ts).

## Instantiating a `PreAuthorizedDebitReadClient`

### Mainnet

```typescript
import { clusterApiUrl, Connection } from "@solana/web3.js";
import { PreAuthorizedDebitReadClientImpl } from "@seabed-labs/pre-authorized-debit";

// You can use any connection object you'd like, this is just an example
const connection = new Connection(clusterApiUrl("mainnet-beta"));

const readClient = PreAuthorizedDebitReadClientImpl.mainnet(connection);
```

### Devnet

```typescript
import { clusterApiUrl, Connection } from "@solana/web3.js";
import { PreAuthorizedDebitReadClientImpl } from "@seabed-labs/pre-authorized-debit";

// You can use any connection object you'd like, this is just an example
const connection = new Connection(clusterApiUrl("devnet"));

const readClient = PreAuthorizedDebitReadClientImpl.devnet(connection);
```

### Custom

Point the read client to a custom deployment on any cluster:

```typescript
import { clusterApiUrl, Connection } from "@solana/web3.js";
import { PreAuthorizedDebitReadClientImpl } from "@seabed-labs/pre-authorized-debit";

const connection = new Connection(/* your connection args */);
const CUSTOM_PAD_PROGRAM_ID = /* your custom program ID */;

const readClient = PreAuthorizedDebitReadClientImpl.custom(
  connection,
  CUSTOM_PAD_PROGRAM_ID
);
```

## Supported Methods

The read client supports the following methods:

* [Fetch IDL from chain](#fetch-idl-from-chain)
* [Derive the Smart Delegate PDA](#derive-the-smart-delegate-pda)
* [Derive the Pre-Authorization PDA](#derive-the-pre-authorization-pda)
* [Fetch the Smart Delegate account](#fetch-the-smart-delegate-account)
* [Fetch a Pre-Authorization account](#fetch-a-pre-authorization-account)
* [Fetch all Pre-Authorizations associated with a token account](#fetch-all-pre-authorizations-associated-with-a-token-account)
* [Fetch all Pre-Authorizations associated with a debit authority](#fetch-all-pre-authorizations-associated-with-a-debit-authority)
* [Check if amount can be debited against a pre-authorization](#check-if-amount-can-be-debited-against-a-pre-authorization)
* [Fetch maximum debit amount for a Pre-Authorization](#fetch-maximum-debit-amount-for-a-pre-authorization)
* [Fetch the token program ID for a token account](#fetch-the-token-program-id-for-a-token-account)
* [Fetch the current owner of a token account](#fetch-the-current-owner-of-a-token-account)
* [Fetch the current delegation of a token account](#fetch-the-current-delegation-of-a-token-account)
* [Fetch the current owner of a Pre-Authorization's token account](#fetch-the-current-owner-of-a-pre-authorizations-token-account)
* [Fetch the current delegation of a Pre-Authorization's token account](#fetch-the-current-delegation-of-a-pre-authorizations-token-account)

### Fetch IDL from chain

Our IDL is already available as [Typescript ](https://github.com/seabed-labs/pre-authorized-debit/blob/main/sdk/pre-authorized-debit-v1/src/pre_authorized_debit_v1.ts)or [JSON](/open-source-primitives/pre-authorized-debit-v1/program/anchor-idl.md#json-idl). If you'd like to directly fetch it on-chain, you can either run the script [here](/open-source-primitives/pre-authorized-debit-v1/program/anchor-idl.md#on-chain-idl) or just use our SDK:

```typescript
const OnchainIDL = await readClient.fetchIdlFromChain();
```

This should return the IDL found [here](https://explorer.solana.com/address/PadV1i1My8wazb6vi37UJ2s1yBDkFN5MYivYN6XgaaR/anchor-program).

### Derive the Smart Delegate PDA

Derive the singleton [`SmartDelegate` account](/open-source-primitives/pre-authorized-debit-v1/program/account-model/smart-delegate.md)'s PDA details (public key and canonical bump):

```typescript
const smartDelegatePDA = readClient.getSmartDelegatePDA();
const { publicKey, bump } = smartDelegatePDA;
```

### Derive the Pre-Authorization PDA

Derive a [`PreAuthorization` account](/open-source-primitives/pre-authorized-debit-v1/program/account-model/pre-authorization.md)'s PDA details (public key and canonical bump) for a particular pair of token account and debit authority:

```typescript
const tokenAccountPubkey = new PublicKey(/* Any token account pubkey */);
const debitAuthorityPubkey = new PublicKey(/* Any pubkey */);

const preAuthorizationPDA = readClient.derivePreAuthorizationPDA(
  tokenAccountPubkey,
  debitAuthorityPubkey
);
const { publicKey, bump } = preAuthorizationPDA;
```

### Fetch the Smart Delegate account

Fetch the singleton [`SmartDelegate` account](/open-source-primitives/pre-authorized-debit-v1/program/account-model/smart-delegate.md) (returns `null` if no account found on-chain)

```typescript
const smartDelegateProgramAccount = await readClient.fetchSmartDelegate();
const {
  publicKey, // PublicKey
  account, // SmartDelegateAccount
} = smartDelegateProgramAccount;

const {
  bump, // number (on-chain type: u8)
} = account;
```

### Fetch a Pre Authorization account

Fetch the [`PreAuthorization` account](/open-source-primitives/pre-authorized-debit-v1/program/account-model/pre-authorization.md) by providing it's public key (returns `null` if no account found on-chain)

```typescript
const preAuthorizationProgramAccount = await readClient.fetchPreAuthorization({
  publicKey: // public key for the account
});

const {
  publicKey, // PublicKey
  account, // PreAuthorizationAccount
} = preAuthorizationProgramAccount;

const {
  bump, // number (on-chain type: u8)
  tokenAccount, // PublicKey,
  debitAuthority, // PublicKey,
  activationUnixTimestamp, // bigint (on-chain i64)
  paused, // boolean
  variant, // PreAuthorizationVariantOneTime | PreAuthorizationVariantRecurring
} = account;

if (variant.type === "oneTime") {
  const {
    amountAuthorized, // bigint (on-chain u64)
    amountDebited, // bigint (on-chain u64)
    expiryUnixTimestamp, // bigint (on-chain i64)
  } = variant;
} else if (variant.type === "recurring") {
  const {
    recurringAmountAuthorized, // bigint (on-chain u64)
    repeatFrequencySeconds, // bigint (on-chain u64)
    resetEveryCycle, // boolean
    numCycles, // number | null (on-chain Option<u64>)
    amountDebitedTotal, // bigint (on-chain u64)
    amountDebitedLastCycle, // bigint (on-chain u64)
    lastDebitedCycle, // bigint (on-chain u64)
  } = variant;
}
```

Fetch it by providing the token account and debit authority instead (returns `null` if no account found on-chain)

```typescript
const preAuthorizationProgramAccount = await readClient.fetchPreAuthorization({
  tokenAccount: // token account pubkey,
  debitAuthority: // debit authority pubkey,
});

// ... (same as previous variant)
```

### Fetch all Pre-Authorizations associated with a token account

Fetch all [`PreAuthorization` accounts](/open-source-primitives/pre-authorized-debit-v1/program/account-model/pre-authorization.md) associated with a particular token account (you can specify one-time, recurring, or all types):

{% code fullWidth="false" %}

```typescript
const tokenAccount: PublicKey = // token account pubkey;
const type = "all";

const preAuthAccounts = await readClient.fetchPreAuthorizationsForTokenAccount(
  tokenAccount, // pubkey
  type, // "oneTime" or "recurring" or "all"
);

for (const account of preAuthAccounts) {
  // ... (access them similar to `fetchPreAuthorization` above)
}
```

{% endcode %}

### Fetch all Pre-Authorizations associated with a debit authority

Fetch all [`PreAuthorization` accounts](/open-source-primitives/pre-authorized-debit-v1/program/account-model/pre-authorization.md) associated with a particular debit authority (you can specify one-time, recurring, or all types):

```typescript
const debitAuthority: PublicKey = // debit authority pubkey;
const type = "all";

const preAuthAccounts = await readClient.fetchPreAuthorizationsForDebitAuthority(
  debitAuthority, // pubkey
  type, // "oneTime" or "recurring" or "all"
);

for (const account of preAuthAccounts) {
  // ... (access them similar to `fetchPreAuthorization` above)
}
```

### Fetch maximum debit amount for a Pre-Authorization

Fetch the maximum possible amount that can be debited by the debit authority for a given pre-authorization:

```typescript
const tokenAccount: PublicKey = // token account pubkey
const debitAuthority: PublicKey = // debit authority pubkey

const maxDebitAmount = await readClient.fetchMaxDebitAmount({
  tokenAccount,
  debitAuthority,
});
```

### Check if amount can be debited against a pre-authorization

Check whether a debit will go through given a pre-authorization pubkey (using the current solana validator time):

```typescript
const res = await readClient.checkDebitAmount({
  preAuthorization: // pre-auth pubkey,
  requestedDebitAmount: // amount to debit (bigint),
  txFeePayer: // the lamports fee payer pubkey for the tx,
  destinationTokenAccount: // optional - defaults to ATA of debitAuthority,
});

if (!res.successful) {
  const { reason } = res;
}
```

Check whether a debit will go through given the token account and debit authority pubkeys (using the current solana validator time):

```typescript
const res = await readClient.checkDebitAmount({
  tokenAccount: // token account pubkey,
  debitAuthority: // debit authority pubkey,
  requestedDebitAmount: // amount to debit (bigint),
  txFeePayer: // the lamports fee payer pubkey for the tx,
  destinationTokenAccount: // optional - defaults to ATA of debitAuthority,
});

if (!res.successful) {
  const { reason } = res;
}
```

### Fetch the token program ID for a token account

Fetch the token program ID (Token or Token2022) for a given token account:

```typescript
const tokenAccount: PublicKey = // token account pubkey
const tokenProgramId = await readClient.fetchTokenProgramIdForTokenAccount(
  tokenAccount
);
```

### Fetch the current owner of a token account

```typescript
const tokenAccount: PublicKey = // token account pubkey
const tokenAccountOwner = await readClient.fetchCurrentOwnerOfTokenAccount(
  tokenAccount
);
```

### Fetch the current delegation of a token account

Fetch the current delegate and delegated amount of a token account (returns null if no delegate or delegated amount is 0):

```typescript
const tokenAccount: PublicKey = // token account pubkey
const delegation = await readClient.fetchCurrentDelegationOfTokenAccount(
  tokenAccount
);

const {
  delegate, // PublicKey
  delegatedAmount, // bigint (on-chain u64)
} = delegation;
```

### Fetch the current owner of a Pre-Authorization's token account

Fetch the current owner of a token account given the pre-authorization public key:

```typescript
const preAuth: PublicKey = // pre-authorization pubkey
const tokenAccountOwner = await readClient.fetchCurrentOwnerOfPreAuthTokenAccount(
  preAuth
);
```

### Fetch the current delegation of a Pre-Authorization's token account

Fetch the current delegate and delegated amount of a token account given the pre-authorization public key (returns null if no delegate or delegated amount is 0):

```typescript
const preAuth: PublicKey = // pre-authorization pubkey
const delegation = await readClient.fetchCurrentDelegationOfPreAuthTokenAccount(
  preAuth
);

const {
  delegate, // PublicKey
  delegatedAmount, // bigint (on-chain u64)
} = delegation;
```


---

# 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.seabed.so/open-source-primitives/pre-authorized-debit-v1/typescript-sdk/read-client.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.
