> For the complete documentation index, see [llms.txt](https://docs.keeta.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.keeta.com/guides/fiat-withdraw-to-bank.md).

# Fiat Withdraw to Bank

This example shows how to initiate a withdraw/payment request from an Anchor that supports outbound payments to a bank.  It assumes KYC has already been completed and shared with the Anchor and that the account holds USD that can be sent.  See the two KYC guides [Add KYC Certificate](https://app.gitbook.com/o/qYWvPguljbNCiIZoKq7U/sites/site_VPB12/s/pitcpcamWc0BKEe28I1D/~/edit/~/changes/85/guides/add-kyc-certificate) and [Share KYC Attributes](https://app.gitbook.com/o/qYWvPguljbNCiIZoKq7U/sites/site_VPB12/s/pitcpcamWc0BKEe28I1D/~/edit/~/changes/85/guides/share-kyc-attributes) for more details on handling KYC.

To run the example on the main network, the following changes are needed.

* Change network from `test` to `main`
* Use the main network Keeta USD Token - `keeta_amnkge74xitii5dsobstldatv3irmyimujfjotftx7plaaaseam4bntb7wnna`

{% stepper %}
{% step %}

### Setup Account and Anchor Client

{% tabs %}
{% tab title="TypeScript" %}
{% code expandable="true" %}

```ts
const account = Account.fromSeed(seed.trim(), 0);
await using userClient = KeetaAnchor.KeetaNet.UserClient.fromNetwork('test', account);
const assetMovementClient = new KeetaAnchor.AssetMovement.Client(userClient);
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code expandable="true" %}

```csharp
using Account userAccount = runtime.Accounts.FromSeed(seed, 0, "ecdsa_secp256k1");

UserClient userClient = UserClient.FromNetwork("test", userAccount);
using AssetMovementClient assetMovementClient = runtime.CreateAssetMovementClient(
  Constants.NodeApi,
	userClient.NetworkAddress,
	userAccount);
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Identify Providers for Transfer

The asset movement client can search the Anchor Resolver metadata to identify providers that can handle the source and destination of the transfer.

{% tabs %}
{% tab title="TypeScript" %}
{% code expandable="true" %}

```ts
const providers = await assetMovementClient.getProvidersForTransfer({
  asset: {
    from: Account.fromPublicKeyString('keeta_any4zllibya6fum3lsoimxmnmeo57nklxlh4c6d6xosfacarfaa3knkiprkmm'),
		to: 'USD'
	},
	from: {
	  type: 'chain',
		chain: { type: 'keeta', networkId: userClient.network }
	},
	to: {
		type: 'bank-account',
		account: { type: 'us' }
	}
});
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code expandable="true" %}

```csharp
using AssetMovementClient assetMovementClient = runtime.CreateAssetMovementClient(
    Constants.NodeApi,
    userClient.NetworkAddress,
    userAccount);

// asset: { from: KeetaUsdAsset, to: 'USD' }
AssetOrPair assetPair = AssetOrPair.Pair(Constants.KeetaUsdAsset, "USD");

// from: chain keeta (networkId)  ->  to: bank-account us
string keetaSource = $"chain:keeta:{userClient.Network}";
IReadOnlyList<AssetProvider> providers = await assetMovementClient.GetProvidersForTransfer(
    new AssetProviderSearch(
        Asset: assetPair,
        From: keetaSource,
        To: Constants.BankAccountUsLocation),
    cancellationToken);
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Construct the Bank Recipient

The Anchor SDK provides specific types for different bank deposits as `BankAccountAddressResolved`.  For US Bank accounts specifically it would use the type `UsBankAccountResolved`

{% tabs %}
{% tab title="TypeScript" %}
{% code expandable="true" %}

```ts
const bankRecipient: UsBankAccountResolved = {
	type: 'bank-account',
	accountType: 'us',
	accountNumber: '99911330003085852',
	routingNumber '021000021',
	accountTypeDetail: 'checking',
	accountOwner: {
		type: 'individual',
		firstName: 'John',
		lastName: 'Doe'
	},
	accountAddress: {
		line1: '123 Main Street',
		line2: 'Apt. 1,
		city: 'White Plains',
		subdivision: 'NY',
		postalCode: '10601',
		country: 'US'
	}
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code expandable="true" %}

```csharp
var bankRecipient = new
{
    type = "bank-account",
    accountType = "us",
    accountNumber = "99911330003085852",
    routingNumber = "021000021",
    bankName = "Chase",
    accountTypeDetail = "checking",
    accountOwner = new
    {
        type = "individual",
        firstName = "John",
        lastName = "Doe",
    },
    accountAddress = new
    {
        line1 = "123 Main Street",
        line2 = "Apt. 1",
        city = "White Plains",
        subdivision = "NY",
        postalCode = "10601",
        country = "US",
    },
};
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Initiate Transfer

Initiating a transfer with the anchor begins the process to submit the payment.  The Anchor will return a specific ID to use as part of the transfer and what account to send the payment too.  These are returned as "instructions" that can be used to construct the Keeta block on the network.

{% tabs %}
{% tab title="TypeScript" %}
{% code expandable="true" %}

```ts
const transfer = await providers[0].initiateTransfer({
  account,
	asset: {
	  from: Account.fromPublicKeyString('keeta_any4zllibya6fum3lsoimxmnmeo57nklxlh4c6d6xosfacarfaa3knkiprkmm'),
		to: 'USD'
	},
	from: {
	  location: {
		  type: 'chain',
			chain: { type: 'keeta', networkId: userClient.network }
		}
	},
	to: {
		location: {
			type: 'bank-account',
				account: { type: 'us' }
			},
		recipient: bankRecipient
		},
	value: 200n // $2.00
});
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code expandable="true" %}

```csharp
AssetTransfer transfer = await assetMovementClient.InitiateTransfer(
	provider,
	new AssetTransferRequest(
	assetPair,
	new AssetTransferSource(keetaSource),
	new AssetTransferDestination(Constants.BankAccountUsLocation, bankRecipient),
		amountToWithdraw.ToString(CultureInfo.InvariantCulture)),
cancellationToken);
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Send the Payment to the Anchor

Use the Keeta Client SDK to construct a transaction on Keeta that sends the funds to the Anchor to process the outbound payment.

{% tabs %}
{% tab title="TypeScript" %}
{% code expandable="true" %}

```ts
const instruction = transfer.instructions[0];
const anchorAccount = Account.toAccount(instruction.sendToAddress);
const usdTokenAccount = Account.fromPublicKeyString('keeta_any4zllibya6fum3lsoimxmnmeo57nklxlh4c6d6xosfacarfaa3knkiprkmm').assertKeyType(Account.AccountKeyAlgorithm.TOKEN);

// Send the required funds to the anchor account with the provided external identifier instructions
const sendBlockResult = await userClient.send(
	anchorAccount,
	200n,
	usdTokenAccount,
	instruction.external
);

```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code expandable="true" %}

```csharp
await userClient.Send(runtime, sendTo, amountToWithdraw, usdToken, external, cancellationToken);
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

### Poll the Anchor for Transfer Status

Once the payment has been submitted, the transfer status can be checked periodically until the transfer is complete.

{% tabs %}
{% tab title="TypeScript" %}
{% code expandable="true" %}

```ts
const transactionResult = await transfer.getTransferStatus();

console.log(transactionResult.transaction.status);
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code expandable="true" %}

```csharp
AssetTransferStatus transactionResult = await transfer.GetTransferStatus(monitorToken);
string? status = transactionResult.Transaction.TryGetProperty("status", out JsonElement statusElement)
  ? statusElement.GetString()
  : null;

Console.WriteLine($"Status: {status ?? transactionResult.Transaction.GetRawText()}");
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## Full Code Example

{% tabs %}
{% tab title="TypeScript" %}
{% @github-files/github-code-block url="<https://github.com/KeetaNetwork/keetanet-examples/blob/main/src/anchor/asset-movement-fiat-withdraw-to-bank.ts>" %}
{% endtab %}

{% tab title="C#" %}
{% @github-files/github-code-block url="<https://github.com/KeetaNetwork/keetanet-examples/blob/main/csharp/src/Anchor/AssetMovementFiatWithdrawToBank.cs>" %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.keeta.com/guides/fiat-withdraw-to-bank.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
