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

# attachFlowSource

> Attach a wallet, exchange, or deposit-address payment source to a Flow payment with the JavaScript SDK, and store the flow's session token.

Attaches a payment source to a flow: a wallet, an exchange, or a deposit address. Attaching issues the flow's session token, and the SDK stores it on the device. Every later action on the flow, such as quoting, submitting, or cancelling, sends that token automatically.

## When to call

Call `attachFlowSource` when `executionState` is `initiated`, `source_attached`, `quoted`, or `signing`. Attaching again before the payment is sent replaces the source, so the payer can change how they pay. Each attach issues a new session token, and the previous token stops working.

Attaching from `signing` requires the current session token, so it works only on the device that attached the source before. A flow in `signing` may already have a payment approved in the wallet.

Attaching needs no session token in the other states. That is how a payer on another device, or with cleared storage, resumes before the payment is sent. Read the flow with [`getFlow`](https://docs.dynamic.xyz/docs/javascript/reference/client/get-flow) first and attach only when its state allows it.

## Usage

```javascript theme={"system"}
import { attachFlowSource, getActiveNetworkId } from '@dynamic-labs-sdk/client';

const { networkId } = await getActiveNetworkId({ walletAccount });

const { flow } = await attachFlowSource({
  flowId: 'your-flow-id',
  sourceType: 'wallet',
  fromAddress: walletAccount.address,
  fromChainName: walletAccount.chain,
  fromChainId: networkId,
});
```

## Parameters

The parameters depend on `sourceType`. [Payment sources](https://docs.dynamic.xyz/docs/flow/payment-sources.md) explains each source.

### Wallet source

The payer pays from a connected wallet. Dynamic screens the wallet address when it is attached.

| Parameter | Type | Description |
| - | - | - |
| `flowId` | `string` | The flow ID. |
| `sourceType` | `'wallet'` | A wallet source. |
| `fromAddress` | `string` | The wallet's address. |
| `fromChainName` | `Chain` | The wallet's chain family: `'EVM'`, `'SOL'`, `'BTC'`, `'SUI'`, or `'TRON'`. |
| `fromChainId` | `string` | Required. The network the wallet pays from, for example `'8453'` for Base or `'101'` for Solana. Read it with `getActiveNetworkId`. |

> [!NOTE]
>
> The SDK's TypeScript type marks `fromChainId` as optional for wallet sources, but the request fails without it. Always pass it.

### Exchange source

The payer pays from an exchange account, such as Coinbase, through a purchase link. Dynamic does not screen exchange sources.

| Parameter | Type | Description |
| - | - | - |
| `flowId` | `string` | The flow ID. |
| `sourceType` | `'exchange'` | An exchange source. |
| `exchangeProvider` | `string` | The exchange's `key`, as returned by [`getFlowSupportedExchanges`](https://docs.dynamic.xyz/docs/javascript/reference/client/get-flow-supported-exchanges), for example `'coinbase'`. |

### Deposit address source

The payer sends funds to an address generated for the payment, from any wallet or exchange. Dynamic does not screen deposit-address sources. Deposit addresses support EVM chains, Solana, Bitcoin, and TRON. The address arrives with the quote, so call [`getFlowQuote`](https://docs.dynamic.xyz/docs/javascript/reference/client/get-flow-quote) next.

| Parameter | Type | Description |
| - | - | - |
| `flowId` | `string` | The flow ID. |
| `sourceType` | `'deposit_address'` | A deposit-address source. |
| `fromChainName` | `Chain` | The chain family the payer sends from: `'EVM'`, `'SOL'`, `'BTC'`, or `'TRON'`. |
| `fromChainId` | `string` | The network the payer sends from, for example `'8453'` for Base or `'101'` for Solana. |
| `refundAddress` | `string` | The payer's address on the same chain family, where the deposit provider returns funds it does not accept. |

Do not pass `fromAddress` with a deposit-address source; the request is rejected. Dynamic does not initiate refunds, and a refund can fail, as described in [Failures and refunds](https://docs.dynamic.xyz/docs/flow/failures-and-refunds.md#refunds).

## Returns

`Promise<FlowSourceResponse>`:

| Field | Type | Description |
| - | - | - |
| `flow` | `Flow` | The flow with `executionState: 'source_attached'`. For an exchange, `flow.exchangeSource.metadata.url` is the purchase link. |
| `sessionToken` | `string` | The flow's session token. The SDK already stored it, so you do not need to keep it. |
| `sessionExpiresAt` | `Date` | When the session token expires. |

## Examples

### Wallet on Solana

```javascript theme={"system"}
import { attachFlowSource } from '@dynamic-labs-sdk/client';

const { flow } = await attachFlowSource({
  flowId: 'your-flow-id',
  sourceType: 'wallet',
  fromAddress: walletAccount.address,
  fromChainName: 'SOL',
  fromChainId: '101',
});
```

### Exchange

```typescript theme={"system"}
import { attachFlowSource } from '@dynamic-labs-sdk/client';

const { flow } = await attachFlowSource({
  flowId: 'your-flow-id',
  sourceType: 'exchange',
  exchangeProvider: 'coinbase',
});

const metadata = flow.exchangeSource?.metadata as { url?: string } | undefined;
const purchaseUrl = metadata?.url;
// Open purchaseUrl from a click handler, then poll the flow. Do not call broadcastFlow.
```

Attaching the exchange again issues a new purchase link. A purchase already completed through an earlier link can still reach your destination.

### Deposit address

```javascript theme={"system"}
import { attachFlowSource, getFlowQuote } from '@dynamic-labs-sdk/client';

await attachFlowSource({
  flowId: 'your-flow-id',
  sourceType: 'deposit_address',
  fromChainName: 'EVM',
  fromChainId: '8453',
  refundAddress: '0xPayerRefundAddress',
});

const quoted = await getFlowQuote({
  flowId: 'your-flow-id',
  fromChainId: '8453',
  fromTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
});

console.log('Send funds to:', quoted.depositAddress);
```

## Errors

| Error | When |
| - | - |
| `FlowSourceBlockedError` | Screening blocked the wallet, with `reason` `sanctions_blocked`. Nothing is saved, so the payer can attach another wallet or source. |
| `FlowExchangeSourceError` | The exchange cannot be used for this flow, or it failed to issue a purchase link. `retryable` is `true` only for `exchange_unavailable`. |
| `FlowStateConflictError` | The flow no longer accepts a source, for example because the payment was sent or the flow ended, or another request changed the flow first. |
| `FlowNotFoundError` | The flow does not exist in the client's environment. |

Attaching from `signing` without the current session token is rejected with `error.code` `session_token_invalid`. Show the flow as processing instead, because the payment may already have been approved. [Handle Flow errors](https://docs.dynamic.xyz/docs/javascript/reference/flow-errors.md) describes each error and how to recover.

## React

`useAttachFlowSource` is a mutation hook. It takes the same parameters, and it writes the returned flow into the `useGetFlow` cache.

```tsx theme={"system"}
import { getActiveNetworkId } from '@dynamic-labs-sdk/client';
import { useAttachFlowSource } from '@dynamic-labs-sdk/react-hooks';

function PayWithWallet({ flowId, walletAccount }) {
  const { mutate: attachFlowSource, isPending } = useAttachFlowSource();

  const attach = async () => {
    const { networkId } = await getActiveNetworkId({ walletAccount });
    attachFlowSource({
      flowId,
      sourceType: 'wallet',
      fromAddress: walletAccount.address,
      fromChainName: walletAccount.chain,
      fromChainId: networkId,
    });
  };

  return (
    <button onClick={attach} disabled={isPending}>
      {isPending ? 'Attaching...' : 'Pay with wallet'}
    </button>
  );
}
```

## Related

* [Build a custom payment UI](https://docs.dynamic.xyz/docs/javascript/reference/flow-ui-guide.md): the wallet, deposit-address, and exchange paths end to end.
* [`getFlowQuote`](https://docs.dynamic.xyz/docs/javascript/reference/client/get-flow-quote): quote the attached source.
* [`getFlowSupportedExchanges`](https://docs.dynamic.xyz/docs/javascript/reference/client/get-flow-supported-exchanges): list the exchanges a flow supports.
* [Screening](https://docs.dynamic.xyz/docs/flow/screening.md): which sources are screened and when.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.