Skip to content

Commit

Permalink
add sep6 docs for wallet-sdk (#283)
Browse files Browse the repository at this point in the history
* add sep6 docs for wallet-sdk

* code example

* add refresh
  • Loading branch information
acharb authored Dec 7, 2023
1 parent 5bc71b9 commit 38ecb23
Showing 1 changed file with 309 additions and 0 deletions.
309 changes: 309 additions & 0 deletions docs/building-apps/wallet/sep6.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
---
title: Programmatic Deposit and Withdrawal
sidebar_position: 60
---

import { LanguageSpecific } from "@site/src/components/LanguageSpecific";

import { WalletCodeExample as CodeExample } from "@site/src/components/WalletCodeExample";
import Header from "./component/header.mdx";

<Header WIPLangs={["kotlin", "dart"]} />

The [SEP-6] standard defines a way for anchors and wallets to interact on behalf of users. Wallets use this standard to facilitate exchanges between on-chain assets (such as stablecoins) and off-chain assets (such as fiat, or other network assets such as BTC).

Please note, this is for _programmatic_ deposits and withdrawals. For hosted deposits and withdrawals, where the anchor interacts with wallets interactively using a popup, please see [Hosted Deposit and Withdrawal](/docs/building-apps/wallet/sep24).

## Get Anchor Information

Let's start with creating a sep6 object, which we'll use for all SEP-6 interactions:

<CodeExample>

```typescript
const sep6 = await anchor.sep6();
```

</CodeExample>

First, let's get information about the anchor's support for [SEP-6]. This request doesn't require authentication, and will return generic info, such as supported currencies, and features supported by the anchor. You can get a full list of returned fields in the [SEP-6 specification](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0006.md#info).

<CodeExample>

```typescript
const info = await sep6.info();
```

</CodeExample>

## Start a deposit

Before getting started, make sure you have connected to the anchor and received an authentication token, as described in the [Stellar Authentication] wallet guide. We will use `authToken` in the examples below as the [SEP-10] authentication token, obtained earlier.

To initiate an operation, we need to know an asset. You can hardcode this. Ensure it is one that is included in the info response above.

:::info

Before starting with the deposit flow, make sure that the user account has [established a trustline](/docs/building-apps/wallet/stellar#modify-assets-trustlines) for the asset you are working with.

:::

Let's start with a basic deposit. We will use `account` to represent our account's public key.

<CodeExample>

```typescript
const deposit = await sep6.deposit({
authToken,
params: {
asset_code,
account,
},
});
```

</CodeExample>

There are several kinds of responses, depending on if the anchor needs more information. All deposits and withdrawals will have these same response types:

### 1. Success response

If the response is successful (HTTP 200), then the anchor is processing the deposit. If it needs additional information, it will communicate it when providing the [transaction info](#getting-transaction-info).

### 2. Still processing, or denied

If an HTTP 403 with data: `customer_info_status` is returned, it means the action is still processing, or not accepted. In this case the `more_info_url` field should have a link describing next steps.

An example response:

```
{
"type": "customer_info_status",
"status": "denied",
"more_info_url": "https://api.example.com/kycstatus?account=GACW7NONV43MZIFHCOKCQJAKSJSISSICFVUJ2C6EZIW5773OU3HD64VI"
}
```

### 3. Needs more KYC info

Another common response is an HTTP 403, with the response: `non_interactive_customer_info_needed`. In this case the anchor needs more KYC information via [SEP-12].

An example response:

```
{
"type": "non_interactive_customer_info_needed",
"fields" : ["family_name", "given_name", "address", "tax_id"]
}
```

Let's show how a wallet can handle this situation. First, we get the deposit response object. If the response includes this error, then we can see which missing fields the anchor is requiring.

<CodeExample>

```typescript
if (deposit.type === "non_interactive_customer_info_needed") {
// handle displaying the missing fields to the user
console.log(deposit.fields);
}
```

</CodeExample>

The wallet will need to handle displaying to the user which fields are missing. And then to add those fields, we can use the sep12 class like so.

<CodeExample>

```typescript
const sep12 = await anchor.sep12(authToken);

// adding the missing kyc info (sample data)
await sep12.add({
sep9Info: {
family_name: "smith",
given_name: "john",
address: "123 street",
tax_id: "123",
},
});
```

</CodeExample>

Then, we can re-call the deposit method like before and it should be successful.

More information about sending KYC info using [SEP-12] can be found in [Providing KYC info](#providing-kyc-info).

## Providing KYC info

An anchor may respond to a deposit or withdrawal request saying they need additional KYC info. To faciliate this, [SEP-6] supports adding a customer's KYC info via [SEP-12]. The user can send in the required info using the sep12 object like below.

Let's add some KYC info for our account using sample data. Binary data (eg. image data), needs to be sent in a separate field. The fields allowed to send to the anchor are described in [SEP-9].

<CodeExample>

```typescript
const sep12 = await anchor.sep12(authToken);

await sep12.add({
sep9Info: {
first_name: "john",
last_name: "smith",
email_address: "[email protected]",
bank_number: "12345",
bank_account_number: "12345",
},
sep9BinaryInfo: {
photo_id_front: Buffer.from("./path/to/image/front"),
photo_id_back: Buffer.from("./path/to/image/back"),
},
});
```

</CodeExample>

## Start a withdrawal

Starting a withdrawal is similar to deposit, and has the same response types as described earlier.

<CodeExample>

```typescript
const resp = await sep6.withdraw({
authToken,
params: {
asset_code: "SRT",
account: accountKp.publicKey,
type: "bank_account",
dest: "123",
dest_extra: "12345",
},
});
```

</CodeExample>

## Get exchange info

If the anchor supports [SEP-38] quotes, it can support deposits that make a bridge between non-equivalent assets. For example, an anchor recieves BRL via bank transfer and in return sends USDC (of equivalent value minus fees) to the user on Stellar.

The sep6 exchange functions allow a user to start an exchange deposit or withdrawal with the anchor, and the anchor can communicate back next steps to the user.

First, let's start a deposit exchange with sample data. Assets are described using the [SEP-38] scheme.

<CodeExample>

```typescript
const resp = await sep6.depositExchange({
authToken,
params: {
destination_asset:
"stellar:SRT:GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B",
source_asset: "iso4217:USD",
amount: "10",
},
});
```

</CodeExample>

The response follows the same types as all the deposits and withdrawals for SEP-6.

Now let's create a withdrawal exchange, which follows the same format as the deposit exchange. We also specify it's bank account withdrawal using the `type` field.

<CodeExample>

```typescript
const resp = await sep6.withdrawExchange({
authToken,
params: {
destination_asset: "iso4217:USD",
source_asset:
"stellar:SRT:GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B",
amount: "10",
type: "bank_account",
},
});
```

</CodeExample>

The response follows the same types as all the deposits and withdrawals for SEP-6.

## Getting Transaction Info

On the typical flow, the wallet would get transaction data to notify users about status updates. This is done via the [SEP-6] `GET /transaction` and `GET /transactions` endpoint.

### Tracking Transaction

Let's look into how to use the sdk to track transaction status changes. We will use the `Watcher` class for this purpose. First, let's initialize it and start tracking a transaction.

<CodeExample>

```typescript
const watcher = anchor.sep6().watcher();

const { stop, refresh } = watcher.watchOneTransaction({
authToken,
assetCode,
id: txId,
onSuccess,
onMessage,
onError,
});
```

</CodeExample>

Alternatively, we can track multiple transactions for the same asset.

<CodeExample>

```typescript
const watcher = anchor.sep6().watcher();

const { stop, refresh } = watcher.watchAllTransactions({
authToken,
assetCode,
account,
onMessage,
onError,
});
```

</CodeExample>

### Fetching Transaction

While `Watcher` class offers powerful tracking capabilities, sometimes it's required to just fetch a transaction (or transactions) once. The `Anchor` class allows you to fetch a transaction by ID, Stellar transaction ID, or external transaction ID:

<CodeExample>

```typescript
const transaction = await anchor
.sep6()
.getTransactionBy({ authToken, id: transactionId });
```

</CodeExample>

It's also possible to fetch transactions by the asset.

<CodeExample>

```typescript
const transactions = await anchor.sep6().getTransactionsForAsset({
authToken,
assetCode,
account,
});
```

</CodeExample>

[sep-6]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0006.md
[sep-9]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0009.md
[sep-10]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md
[sep-12]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0012.md
[sep-38]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0038.md
[stellar authentication]: ./sep10.mdx

0 comments on commit 38ecb23

Please sign in to comment.