Skip to content

Commit

Permalink
Merge branch 'release/1.3.0' into acharb-integration-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
acharb committed Nov 22, 2023
2 parents 7444a4b + db60e08 commit 93bdf01
Show file tree
Hide file tree
Showing 6 changed files with 524 additions and 7 deletions.
180 changes: 180 additions & 0 deletions src/walletSdk/Anchor/Sep6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { AxiosInstance } from "axios";
import queryString from "query-string";

import { Anchor } from "../Anchor";
import { ServerRequestFailedError } from "../Exceptions";
import {
Sep6Info,
Sep6Params,
Sep6DepositParams,
Sep6WithdrawParams,
Sep6DepositResponse,
Sep6WithdrawResponse,
Sep6ExchangeParams,
} from "../Types";

/**
* Flow for creating deposits and withdrawals with an anchor using SEP-6.
* For an interactive flow use Sep24 instead.
* @see {@link https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0006.md}
* Do not create this object directly, use the Anchor class.
* @class
*/
export class Sep6 {
private anchor: Anchor;
private httpClient: AxiosInstance;
private anchorInfo: Sep6Info;

/**
* Creates a new instance of the Sep6 class.
* @constructor
* @param {Sep6Params} params - Parameters to initialize the Sep6 instance.
*/
constructor(params: Sep6Params) {
const { anchor, httpClient } = params;

this.anchor = anchor;
this.httpClient = httpClient;
}

/**
* Get SEP-6 anchor information.
* If `shouldRefresh` is set to `true`, it fetches fresh values; otherwise, it returns cached values if available.
* @param {boolean} [shouldRefresh=false] - Flag to force a refresh of TOML values.
* @returns {Promise<Sep6Info>} - SEP-6 information about the anchor.
*/
async info(shouldRefresh?: boolean): Promise<Sep6Info> {
if (this.anchorInfo && !shouldRefresh) {
return this.anchorInfo;
}

const { transferServer } = await this.anchor.sep1();
try {
const resp = await this.httpClient.get(`${transferServer}/info`);
this.anchorInfo = resp.data;
return resp.data;
} catch (e) {
throw new ServerRequestFailedError(e);
}
}

/**
* Deposits funds using the SEP-6 protocol. Next steps by
* the anchor are given in the response.
*
* @param {object} options - The options for the deposit.
* @param {string} options.authToken - The authentication token.
* @param {Sep6DepositParams} options.params - The parameters for the deposit request.
*
* @returns {Promise<Sep6DepositResponse>} Sep6 deposit response, containing next steps if needed
* to complete the deposit.
*
* @throws {Error} If an unexpected error occurs during the deposit operation.
*/
async deposit({
authToken,
params,
}: {
authToken: string;
params: Sep6DepositParams;
}): Promise<Sep6DepositResponse> {
return this.flow({ type: "deposit", authToken, params });
}

/**
* Initiates a withdrawal using SEP-6.
*
* @param {object} options - The options for the withdrawal operation.
* @param {string} options.authToken - The authentication token.
* @param {Sep6WithdrawParams} options.params - The parameters for the withdrawal request.
*
* @returns {Promise<Sep6WithdrawResponse>} Sep6 withdraw response.
*/
async withdraw({
authToken,
params,
}: {
authToken: string;
params: Sep6WithdrawParams;
}): Promise<Sep6WithdrawResponse> {
return this.flow({ type: "withdraw", authToken, params });
}

/**
* Similar to the SEP-6 deposit function, but for non-equivalent assets
* that require an exchange.
*
* @param {object} options - The options for the deposit exchange.
* @param {string} options.authToken - The authentication token.
* @param {Sep6ExchangeParams} options.params - The parameters for the deposit request.
*
* @returns {Promise<Sep6DepositResponse>} Sep6 deposit response, containing next steps if needed
* to complete the deposit.
*
* @throws {Error} If an unexpected error occurs during the deposit operation.
*/
async depositExchange({
authToken,
params,
}: {
authToken: string;
params: Sep6ExchangeParams;
}): Promise<Sep6DepositResponse> {
return this.flow({ type: "deposit-exchange", authToken, params });
}

/**
* Similar to the SEP-6 withdraw function, but for non-equivalent assets
* that require an exchange.
*
* @param {object} options - The options for the deposit exchange.
* @param {string} options.authToken - The authentication token.
* @param {Sep6ExchangeParams} options.params - The parameters for the deposit request.
*
* @returns {Promise<Sep6WithdrawResponse>} Sep6 withdraw response, containing next steps if needed
* to complete the withdrawal.
*
* @throws {Error} If an unexpected error occurs during the deposit operation.
*/
async withdrawExchange({
authToken,
params,
}: {
authToken: string;
params: Sep6ExchangeParams;
}): Promise<Sep6WithdrawResponse> {
return this.flow({ type: "withdraw-exchange", authToken, params });
}

private async flow({
type,
authToken,
params,
}: {
type: "deposit" | "withdraw" | "deposit-exchange" | "withdraw-exchange";
authToken: string;
params: Sep6DepositParams | Sep6WithdrawParams | Sep6ExchangeParams;
}) {
const { transferServer } = await this.anchor.sep1();

try {
const resp = await this.httpClient.get(
`${transferServer}/${type}?${queryString.stringify(params)}`,
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${authToken}`,
},
},
);
return resp.data;
} catch (e) {
if (e.response?.data?.type === "non_interactive_customer_info_needed") {
return e.response?.data;
} else if (e.response?.data?.type === "customer_info_status") {
return e.response?.data;
}
throw e;
}
}
}
19 changes: 19 additions & 0 deletions src/walletSdk/Anchor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ServerRequestFailedError,
KYCServerNotFoundError,
} from "../Exceptions";
import { Sep6 } from "./Sep6";
import { Sep24 } from "./Sep24";
import { AnchorServiceInfo, TomlInfo } from "../Types";
import { parseToml } from "../Utils";
Expand All @@ -21,6 +22,8 @@ type AnchorParams = {
language: string;
};

export type Transfer = Sep6;

export type Interactive = Sep24;

export type Auth = Sep10;
Expand Down Expand Up @@ -82,6 +85,22 @@ export class Anchor {
return this.sep1(shouldRefresh);
}

/**
* Creates new transfer flow for given anchor. It can be used for withdrawal or deposit.
* @returns {Sep6} - flow service.
*/
sep6(): Sep6 {
return new Sep6({ anchor: this, httpClient: this.httpClient });
}

/**
* Creates new transfer flow using the `sep6` method.
* @returns {Transfer} - transfer flow service.
*/
transfer(): Transfer {
return this.sep6();
}

/**
* Create new auth object to authenticate account with the anchor using SEP-10.
* @returns {Promise<Sep10>} - The SEP-10 authentication manager.
Expand Down
1 change: 1 addition & 0 deletions src/walletSdk/Types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export * from "./anchor";
export * from "./auth";
export * from "./horizon";
export * from "./recovery";
export * from "./sep6";
export * from "./sep12";
export * from "./sep24";
export * from "./utils";
Expand Down
168 changes: 168 additions & 0 deletions src/walletSdk/Types/sep6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { AxiosInstance } from "axios";
import { Anchor } from "../Anchor";

export interface Sep6EndpointInfo {
enabled: boolean;
authentication_required?: boolean;
description?: string;
}

export interface Sep6DepositInfo {
enabled: boolean;
authentication_required?: boolean;
fee_fixed?: number;
fee_percent?: number;
min_amount?: number;
max_amount?: number;
fields?: {
[key: string]: {
description: string;
optional?: boolean;
choices?: string[];
};
};
}

export interface Sep6WithdrawInfo {
enabled: boolean;
authentication_required?: boolean;
fee_fixed?: number;
fee_percent?: number;
min_amount?: number;
max_amount?: number;
types?: {
[key: string]: {
fields?: {
[key: string]: {
description: string;
optional?: boolean;
choices?: string[];
};
};
};
};
}

export interface Sep6Info {
deposit: { [key: string]: Sep6DepositInfo };
"deposit-exchange": { [key: string]: Sep6DepositInfo };
withdraw: { [key: string]: Sep6WithdrawInfo };
"withdraw-exchange": { [key: string]: Sep6WithdrawInfo };
fee: {
enabled: boolean;
description: string;
};
transactions: Sep6EndpointInfo;
transaction: Sep6EndpointInfo;
features: {
account_creation: boolean;
claimable_balances: boolean;
};
}

export type Sep6Params = {
anchor: Anchor;
httpClient: AxiosInstance;
};

export interface Sep6DepositParams {
asset_code: string;
account: string;
memo_type?: string;
memo?: string;
email_address?: string;
type?: string;
lang?: string;
on_change_callback?: string;
amount?: string;
country_code?: string;
claimable_balance_supported?: string;
customer_id?: string;
}

export interface Sep6WithdrawParams {
asset_code: string;
type: string;
dest?: string;
dest_extra?: string;
account?: string;
memo?: string;
lang?: string;
on_change_callback?: string;
amount?: string;
country_code?: string;
refund_memo?: string;
refund_memo_type?: string;
customer_id?: string;
}

export type Sep6DepositResponse =
| Sep6DepositSuccess
| Sep6MissingKYC
| Sep6Pending;

export interface Sep6DepositSuccess {
how?: string;
instructions?: {
[key: string]: {
value: string;
description: string;
};
};
id?: string;
eta?: number;
min_amoun?: number;
max_amount?: number;
fee_fixed?: number;
fee_percent?: number;
extra_info?: { message?: string };
}

export interface Sep6MissingKYC {
type: string;
fields: Array<string>;
}

export interface Sep6Pending {
type: string;
status: string;
more_info_url?: string;
eta?: number;
}

export type Sep6WithdrawResponse =
| Sep6WithdrawSuccess
| Sep6MissingKYC
| Sep6Pending;

export interface Sep6WithdrawSuccess {
account_id?: string;
memo_type?: string;
memo?: string;
id?: string;
eta?: number;
min_amount?: number;
max_amount?: number;
fee_fixed?: number;
fee_percent?: number;
extra_info?: { message?: string };
}

export interface Sep6ExchangeParams {
destination_asset: string;
source_asset: string;
amount: string;
account?: string;
quote_id?: string;
memo_type?: string;
memo?: string;
email_address?: string;
type?: string;
lang?: string;
on_change_callback?: string;
country_code?: string;
claimable_balance_supported?: string;
customer_id?: string;
refund_memo?: string;
refund_memo_type?: string;
}
Loading

0 comments on commit 93bdf01

Please sign in to comment.