From 2b815b70b0c96f16e2b89e6fd2c0b71f54404be0 Mon Sep 17 00:00:00 2001 From: Morley Zhi Date: Wed, 17 Jul 2019 15:26:51 -0400 Subject: [PATCH] Fee calculation: Support blank fixed or percent costs (#82) --- package.json | 2 +- src/transfers/DepositProvider.test.ts | 65 +++++++++++++++++++++++++++ src/transfers/TransferProvider.ts | 18 ++++---- src/transfers/parseInfo.ts | 2 +- src/types/transfers.ts | 18 +++++--- 5 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 src/transfers/DepositProvider.test.ts diff --git a/package.json b/package.json index 2569b78f..b6ee5607 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@stellar/wallet-sdk", - "version": "0.0.3-rc.12", + "version": "0.0.3-rc.13", "description": "Libraries to help you write Stellar-enabled wallets in Javascript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/transfers/DepositProvider.test.ts b/src/transfers/DepositProvider.test.ts new file mode 100644 index 00000000..45efbb74 --- /dev/null +++ b/src/transfers/DepositProvider.test.ts @@ -0,0 +1,65 @@ +import { DepositProvider } from "./DepositProvider"; + +import { DepositInfo } from "../types"; + +describe("fetchFinalFee", () => { + test("AnchorUSD", async () => { + const info: DepositInfo = { + USD: { + assetCode: "USD", + fee: { type: "simple", fixed: 5, percent: 1 }, + minAmount: 15, + fields: [ + { + description: "your email address for transaction status updates", + name: "email_address", + }, + { + description: "amount in USD that you plan to deposit", + name: "amount", + }, + ], + }, + }; + + const provider = new DepositProvider("test"); + + expect( + await provider.fetchFinalFee({ + supportedAssets: info, + assetCode: info.USD.assetCode, + amount: "15", + type: "", + }), + ).toEqual(5.15); + }); + + test("EUR from Nucleo staging", async () => { + const info: DepositInfo = { + EUR: { + assetCode: "EUR", + fee: { type: "simple", percent: 0.5 }, + minAmount: 1, + maxAmount: 1000000000, + fields: [ + { + description: "Type of deposit method for EUR", + choices: ["SWIFT", "SEPA"], + name: "type", + }, + ], + }, + }; + + const provider = new DepositProvider("test"); + + expect( + await provider.fetchFinalFee({ + supportedAssets: info, + assetCode: info.EUR.assetCode, + amount: "10", + type: "", + }), + ).toEqual(0.05); + }); +}); diff --git a/src/transfers/TransferProvider.ts b/src/transfers/TransferProvider.ts index 625ffb06..2d28267d 100644 --- a/src/transfers/TransferProvider.ts +++ b/src/transfers/TransferProvider.ts @@ -2,6 +2,7 @@ import queryString from "query-string"; import { DepositInfo, + Fee, FeeArgs, Info, RawInfoResponse, @@ -33,25 +34,24 @@ export abstract class TransferProvider { | Promise; protected async fetchFinalFee(args: FeeArgs): Promise { - const { supportedAssets, ...rest } = args; + const { supportedAssets, assetCode, amount } = args; - if (!supportedAssets[rest.assetCode]) { - throw new Error( - `Can't get fee for an unsupported asset, '${rest.assetCode}`, - ); + if (!supportedAssets[assetCode]) { + throw new Error(`Can't get fee for an unsupported asset, '${assetCode}`); } - const { fee } = supportedAssets[rest.assetCode]; + const { fee } = supportedAssets[assetCode]; switch (fee.type) { case "none": return 0; case "simple": const simpleFee = fee as SimpleFee; return ( - (simpleFee.percent / 100) * Number(rest.amount) + simpleFee.fixed + ((simpleFee.percent || 0) / 100) * Number(amount) + + (simpleFee.fixed || 0) ); case "complex": const response = await fetch( - `${this.transferServer}/fee?${queryString.stringify(rest)}`, + `${this.transferServer}/fee?${queryString.stringify(args)}`, ); const { fee: feeResponse } = await response.json(); return feeResponse as number; @@ -59,7 +59,7 @@ export abstract class TransferProvider { default: throw new Error( `Invalid fee type found! Got '${ - fee.type + (fee as Fee).type }' but expected one of 'none', 'simple', 'complex'`, ); } diff --git a/src/transfers/parseInfo.ts b/src/transfers/parseInfo.ts index 8ac3fa04..30e34be5 100644 --- a/src/transfers/parseInfo.ts +++ b/src/transfers/parseInfo.ts @@ -52,7 +52,7 @@ const parseFee = ( } else { return { type: feeEnabled ? "complex" : "none", - }; + } as Fee; } }; diff --git a/src/types/transfers.ts b/src/types/transfers.ts index 22936d9c..47b73cf8 100644 --- a/src/types/transfers.ts +++ b/src/types/transfers.ts @@ -92,7 +92,7 @@ export interface DepositAssetInfo { assetCode: string; fee: Fee; minAmount: number; - maxAmount: number; + maxAmount?: number; fields: Field[]; } @@ -195,16 +195,22 @@ export interface Field { choices?: string[]; } -export interface Fee { - type: "none" | "simple" | "complex"; +export interface NoneFee { + type: "none"; } -export interface SimpleFee extends Fee { +export interface ComplexFee { + type: "complex"; +} + +export interface SimpleFee { type: "simple"; - fixed: number; - percent: number; + fixed?: number; + percent?: number; } +export type Fee = NoneFee | ComplexFee | SimpleFee; + export interface Memo { type: "text" | "id" | "hash"; value: string;