UNPKG

@1amageek/tradable

Version:

Cloud Firestore model framework for TypeScript - Google

947 lines 51.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Manager = void 0; const stockManager_1 = require("./stockManager"); const balanceManager_1 = require("./balanceManager"); const orderManager_1 = require("./orderManager"); const PayoutManager_1 = require("./PayoutManager"); const index_1 = require("./index"); const firestore_1 = require("@google-cloud/firestore"); class Manager { constructor(inventoryStock, sku, orderItem, order, tradeTransaction, balanceTransaction, payout, user, account) { this._InventoryStock = inventoryStock; this._SKU = sku; this._OrderItem = orderItem; this._Order = order; this._TradeTransaction = tradeTransaction; this._BalanceTransaction = balanceTransaction; this._Payout = payout; this._User = user; this._Account = account; this.stockManager = new stockManager_1.StockManager(this._User, this._InventoryStock, this._SKU, this._TradeTransaction); this.balanceManager = new balanceManager_1.BalanceManager(this._BalanceTransaction, this._Account); this.orderManager = new orderManager_1.OrderManager(this._User, this._Order); this.payoutManager = new PayoutManager_1.PayoutManager(this._BalanceTransaction, this._Payout, this._Account); } async runTransaction(order, option, block) { if (order instanceof this._Order) { const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ${order.path}, Manager required delegate.`); } const tradeDelegate = this.tradeDelegate; if (!tradeDelegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ${order.path}, Manager required trade delegate.`); } this.stockManager.delegate = tradeDelegate; try { return await index_1.firestore.runTransaction(async (transaction) => { return await block(order, option, transaction); }); } catch (error) { throw error; } } if (order instanceof firestore_1.DocumentReference) { const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ${order.path}, Manager required delegate.`); } const tradeDelegate = this.tradeDelegate; if (!tradeDelegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ${order.path}, Manager required trade delegate.`); } this.stockManager.delegate = tradeDelegate; const reference = order; try { return await index_1.firestore.runTransaction(async (transaction) => { const orderSnapshot = await transaction.get(reference); const order = new this._Order(orderSnapshot.id, orderSnapshot.data()).setData(orderSnapshot.data()); return await block(order, option, transaction); }); } catch (error) { throw error; } } } // /** // * オーダーをSellerに渡して、オーソリを作る // * // * @param order // * @param orderItems // * @param paymentOptions // */ // async reserve(order: Order, orderItems: OrderItem[], paymentOptions: PaymentOptions) { // try { // if (!(order.paymentStatus === OrderPaymentStatus.none)) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order paymentStatus is invalid.`) // } // const delegate: TransactionDelegate | undefined = this.delegate // if (!delegate) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, Manager required delegate.`) // } // const tradeDelegate: TradeDelegate | undefined = this.tradeDelegate // if (!tradeDelegate) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, Manager required trade delegate.`) // } // this.stockManager.delegate = tradeDelegate // const validator = new OrderValidator(this._Order, this._OrderItem) // const validationError = validator.validate(order, orderItems) // if (validationError) { // throw validationError // } // if (order.amount === 0) { // try { // return await firestore.runTransaction(async (transaction) => { // return new Promise(async (resolve, reject) => { // try { // const tasks = [] // for (const orderItem of orderItems) { // const skuID = orderItem.sku // if (orderItem.type === OrderItemType.sku) { // if (!skuID) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order item is sku required.`) // } // const task = this.stockManager.reserve(order, orderItem, transaction) // tasks.push(task) // } // } // await Promise.all(tasks) // order.paymentStatus = OrderPaymentStatus.authorized // this.orderManager.update(order, {}, {}, transaction) // const reuslt: ReserveResult = {} // resolve(reuslt) // } catch (error) { // reject(error) // } // }) // }) // } catch (error) { // throw error // } // } else { // try { // let authorizeResult: { [key: string]: any } | undefined = undefined // return await firestore.runTransaction(async (transaction) => { // return new Promise(async (resolve, reject) => { // try { // const tasks = [] // for (const orderItem of orderItems) { // const skuID = orderItem.sku // if (orderItem.type === OrderItemType.sku) { // if (!skuID) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order item is sku required.`) // } // const task = this.stockManager.reserve(order, orderItem, transaction) // tasks.push(task) // } // } // await Promise.all(tasks) // if (!authorizeResult) { // authorizeResult = await delegate.authorize(order.currency, order.amount, order, paymentOptions) // } // order.paymentStatus = OrderPaymentStatus.authorized // this.orderManager.update(order, {}, // { [paymentOptions.vendorType]: authorizeResult } // , transaction) // const result: ReserveResult = { // authorizeResult: authorizeResult // } // resolve(result) // } catch (error) { // reject(error) // } // }) // }) // } catch (error) { // throw error // } // } // } catch (error) { // throw error // } // } // /** // * オーダーをSellerに渡して、オーソリを作る // * // * @param order // * @param orderItems // * @param paymentOptions // */ // async reserveCancel(order: Order, orderItems: OrderItem[], paymentOptions: PaymentOptions) { // try { // if (!(order.paymentStatus === OrderPaymentStatus.authorized)) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order paymentStatus is invalid.`) // } // const delegate: TransactionDelegate | undefined = this.delegate // if (!delegate) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, Manager required delegate.`) // } // const validator = new OrderValidator(this._Order, this._OrderItem) // const validationError = validator.validate(order, orderItems) // if (validationError) { // throw validationError // } // if (order.amount === 0) { // try { // return await firestore.runTransaction(async (transaction) => { // return new Promise(async (resolve, reject) => { // try { // order.paymentStatus = OrderPaymentStatus.cancelled // order.isCancelled = true // this.orderManager.update(order, {}, {}, transaction) // resolve({}) // } catch (error) { // reject(error) // } // }) // }) // } catch (error) { // throw error // } // } else { // try { // let authorizeCancelResult: { [key: string]: any } | undefined = undefined // return await firestore.runTransaction(async (transaction) => { // return new Promise(async (resolve, reject) => { // try { // if (!authorizeCancelResult) { // authorizeCancelResult = await delegate.authorizeCancel(order.currency, order.amount, order, paymentOptions) // } // order.paymentStatus = OrderPaymentStatus.cancelled // order.isCancelled = true // this.orderManager.update(order, {}, // { [paymentOptions.vendorType]: authorizeCancelResult } // , transaction) // const result: ReserveCancelResult = { // authorizeCancelResult: authorizeCancelResult // } // resolve(result) // } catch (error) { // reject(error) // } // }) // }) // } catch (error) { // throw error // } // } // } catch (error) { // throw error // } // } // /** // * 在庫を減らす // * // * @param order // * @param orderItems // * @param paymentOptions // */ // async trade(order: Order, orderItems: OrderItem[], paymentOptions: PaymentOptions) { // try { // if (!(order.paymentStatus === OrderPaymentStatus.authorized)) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order paymentStatus is invalid.`) // } // const validator = new OrderValidator(this._Order, this._OrderItem) // const validationError = validator.validate(order, orderItems) // if (validationError) { // throw validationError // } // const tradeDelegate: TradeDelegate | undefined = this.tradeDelegate // if (!tradeDelegate) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, Manager required trade delegate.`) // } // this.stockManager.delegate = tradeDelegate // try { // return await firestore.runTransaction(async (transaction) => { // return new Promise(async (resolve, reject) => { // try { // const tasks = [] // for (const orderItem of orderItems) { // const productID = orderItem.product // const skuID = orderItem.sku // const quantity = orderItem.quantity // if (orderItem.type === OrderItemType.sku) { // if (!skuID) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order item is sku required.`) // } // const tradeInformation: TradeInformation = { // type: TradeType.normal, // selledBy: order.selledBy, // purchasedBy: order.purchasedBy, // order: order.id, // sku: skuID, // product: productID // } // const task = this.stockManager.trade(tradeInformation, quantity, transaction) // tasks.push(task) // } // } // const stockTransactions = await Promise.all(tasks) // const tradeTransactions = await Promise.all(stockTransactions.map(stockTransaction => stockTransaction.commit())) // this.orderManager.update(order, {}, {}, transaction) // const reuslt: TradeResult<TradeTransaction> = { // tradeTransactions: tradeTransactions // } // resolve(reuslt) // } catch (error) { // reject(error) // } // }) // }) // } catch (error) { // throw error // } // } catch (error) { // throw error // } // } // /** // * 予約したオーダーの決済処理 // * // * @param order // * @param orderItems // * @param paymentOptions // */ // async capture(order: Order, orderItems: OrderItem[], paymentOptions: PaymentOptions) { // try { // if (!(order.paymentStatus === OrderPaymentStatus.authorized)) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order paymentStatus is invalid.`) // } // const delegate: TransactionDelegate | undefined = this.delegate // if (!delegate) { // throw new TradableError(TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, Manager required delegate.`) // } // const validator = new OrderValidator(this._Order, this._OrderItem) // const validationError = validator.validate(order, orderItems) // if (validationError) { // throw validationError // } // if (order.amount === 0) { // try { // return await firestore.runTransaction(async (transaction) => { // return new Promise(async (resolve, reject) => { // // stock // try { // // payment // order.paymentStatus = OrderPaymentStatus.paid // this.orderManager.update(order, {}, {}, transaction) // const reuslt: CaptureResult = { // paymentResult: {} // } // resolve(reuslt) // } catch (error) { // reject(error) // } // }) // }) // } catch (error) { // throw error // } // } else { // try { // let paymentResult: { [key: string]: any } | undefined = undefined // return await firestore.runTransaction(async (transaction) => { // return new Promise(async (resolve, reject) => { // try { // if (!paymentResult) { // paymentResult = await delegate.pay(order.currency, order.amount, order, paymentOptions) // } // // payment // const balanceTransaction = this.balanceManager.pay(order.purchasedBy, // order.id, // order.currency, // order.amount, // { [paymentOptions.vendorType]: paymentResult } // , transaction) // order.paymentStatus = OrderPaymentStatus.paid // this.orderManager.update(order, {}, // { [paymentOptions.vendorType]: paymentResult } // , transaction) // resolve({ // balanceTransaction: balanceTransaction, // paymentResult: paymentResult // }) // } catch (error) { // if (paymentResult) { // reject({ // paymentResult: paymentResult // }) // } else { // reject(error) // } // } // }) // }) // } catch (error) { // if (error instanceof TradableError) { // order.paymentStatus = OrderPaymentStatus.paymentFailure // try { // await order.update() // } catch (error) { // throw error // } // throw error // } // let captureResult = error // try { // if (captureResult.paymentResult) { // const refundResult = await delegate.refund(order.currency, order.amount, order, paymentOptions, `[Manager] Invalid order ORDER/${order.id}, transaction failure.`) // captureResult.refundResult = refundResult // } // throw captureResult // } catch (error) { // order.paymentStatus = OrderPaymentStatus.paymentFailure // try { // await order.update() // } catch (error) { // throw error // } // throw error // } // } // } // } catch (error) { // throw error // } // } /** * 決済処理、在庫処理を同時に行う * @param order * @param orderItems * @param paymentOptions */ async checkout(orderReference, paymentOptions) { const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ${orderReference.path}, Manager required delegate.`); } const tradeDelegate = this.tradeDelegate; if (!tradeDelegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ${orderReference.path}, Manager required trade delegate.`); } this.stockManager.delegate = tradeDelegate; let paymentResult = undefined; try { return await index_1.firestore.runTransaction(async (transaction) => { const orderSnapshot = await transaction.get(orderReference); const order = new this._Order(orderSnapshot.id, orderSnapshot.data()).setData(orderSnapshot.data()); if (!(order.paymentStatus === index_1.OrderPaymentStatus.none)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order paymentStatus is invalid.`); } if (order.amount < 0) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order amount is invalid.`); } const stockTransactions = await this.stockManager.trade(order, transaction); const tradeTransactions = await Promise.all(stockTransactions.map(stockTransaction => stockTransaction.commit())); if (order.amount === 0) { order.paymentStatus = index_1.OrderPaymentStatus.paid; this.orderManager.update(order, {}, {}, transaction); const reuslt = { tradeTransactions: tradeTransactions }; return reuslt; } else { if (!paymentResult) { paymentResult = await delegate.pay(order.currency, order.amount, order, paymentOptions); } // payment const balanceTransaction = this.balanceManager.charge(order.purchasedBy, order.id, order.currency, order.amount, { [paymentOptions.vendorType]: paymentResult }, transaction); order.paymentStatus = index_1.OrderPaymentStatus.paid; this.orderManager.update(order, {}, { [paymentOptions.vendorType]: paymentResult }, transaction); return { tradeTransactions: tradeTransactions, balanceTransaction: balanceTransaction, paymentResult: paymentResult }; } }); } catch (error) { if (paymentResult) { // TODO: refund // try { // const refundResult = await delegate.refund(order.currency, order.amount, order, paymentOptions, `[Manager] Invalid order ORDER/${order.id}, transaction failure.`) // } catch (error) { // order.paymentStatus = OrderPaymentStatus.paymentFailure // try { // await order.update() // } catch (error) { // throw error // } // throw error // } throw error; } throw error; } } /** * 支払い後、支払いをキャンセルする * * @param order * @param orderItems * @param paymentOptions */ async checkoutCancel(order, orderItems, paymentOptions) { try { const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid orderCancel ORDER/${order.id}, Manager required delegate.`); } if (!(order.paymentStatus === index_1.OrderPaymentStatus.paid)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid orderCancel ORDER/${order.id}, This order status is invalid.`); } const tradeDelegate = this.tradeDelegate; if (!tradeDelegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, Manager required trade delegate.`); } this.stockManager.delegate = tradeDelegate; if (order.amount === 0) { try { return await index_1.firestore.runTransaction(async (transaction) => { // stock const tasks = []; for (const orderItem of orderItems) { const productID = orderItem.product; const skuID = orderItem.sku; if (orderItem.type === index_1.OrderItemType.sku) { if (!skuID) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order item is sku required.`); } // const tradeInformation: TradeInformation = { // selledBy: order.selledBy, // purchasedBy: order.purchasedBy, // order: order.id, // sku: skuID, // product: productID, // metadata: paymentOptions.metadata // } orderItem.status = index_1.OrderItemStatus.cancelled; const task = this.stockManager.cancel(order, orderItem, transaction); tasks.push(task); } } const stockTransactions = await Promise.all(tasks); const tradeTransactions = await Promise.all(stockTransactions.map(stockTransaction => stockTransaction.commit())); order.isCancelled = true; order.paymentStatus = index_1.OrderPaymentStatus.cancelled; this.orderManager.update(order, {}, {}, transaction); return ({ tradeTransactions: tradeTransactions }); }); } catch (error) { throw error; } } else { try { let refundResult = undefined; return await index_1.firestore.runTransaction(async (transaction) => { try { const amount = order.amount * (1 - paymentOptions.refundFeeRate); if (!refundResult) { refundResult = await delegate.refund(order.currency, amount, order, paymentOptions); } // stock const tasks = []; for (const orderItem of orderItems) { const productID = orderItem.product; const skuID = orderItem.sku; if (orderItem.type === index_1.OrderItemType.sku) { if (!skuID) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order item is sku required.`); } // const tradeInformation: TradeInformation = { // selledBy: order.selledBy, // purchasedBy: order.purchasedBy, // order: order.id, // sku: skuID, // product: productID, // metadata: paymentOptions.metadata // } orderItem.status = index_1.OrderItemStatus.cancelled; const task = this.stockManager.cancel(order, orderItem, transaction); tasks.push(task); } } const stockTransactions = await Promise.all(tasks); const tradeTransactions = await Promise.all(stockTransactions.map(stockTransaction => stockTransaction.commit())); // payment const balanceTransaction = this.balanceManager.refund(order.purchasedBy, order.id, order.currency, amount, { [paymentOptions.vendorType]: refundResult }, transaction); order.isCancelled = true; order.paymentStatus = index_1.OrderPaymentStatus.cancelled; this.orderManager.update(order, {}, { [paymentOptions.vendorType]: refundResult }, transaction); return ({ tradeTransactions: tradeTransactions, balanceTransaction: balanceTransaction, refundResult: refundResult }); } catch (error) { if (refundResult) { throw ({ refundResult: refundResult }); } else { throw error; } } }); } catch (error) { if (error instanceof index_1.TradableError) { order.paymentStatus = index_1.OrderPaymentStatus.cancelFailure; try { await order.update(); } catch (error) { throw error; } throw error; } let CheckoutCancelResult = error; return CheckoutCancelResult; } } } catch (error) { throw error; } } /** * 支払い後、支払いの内容を変更する * * @param order * @param orderItem * @param itemID * @param paymentOptions */ async checkoutChange(order, orderItem, item, paymentOptions) { try { const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid orderCancel ORDER/${order.id}, Manager required delegate.`); } if (!(order.paymentStatus === index_1.OrderPaymentStatus.paid)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid orderCancel ORDER/${order.id}, This order status is invalid.`); } const tradeDelegate = this.tradeDelegate; if (!tradeDelegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, Manager required trade delegate.`); } this.stockManager.delegate = tradeDelegate; if (orderItem.amount === 0) { try { return await index_1.firestore.runTransaction(async (transaction) => { // stock const tasks = []; const productID = orderItem.product; const skuID = orderItem.sku; if (orderItem.type === index_1.OrderItemType.sku) { if (!skuID) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order item is sku required.`); } // const tradeInformation: TradeInformation = { // selledBy: order.selledBy, // purchasedBy: order.purchasedBy, // order: order.id, // sku: skuID, // product: productID, // metadata: paymentOptions.metadata // } orderItem.status = index_1.OrderItemStatus.changed; const task = this.stockManager.itemCancel(order, orderItem, item, transaction); tasks.push(task); } const stockTransactions = await Promise.all(tasks); const tradeTransactions = await Promise.all(stockTransactions.map(stockTransaction => stockTransaction.commit())); this.orderManager.update(order, {}, {}, transaction); return ({ tradeTransactions: tradeTransactions }); }); } catch (error) { throw error; } } else { try { let refundResult = undefined; return await index_1.firestore.runTransaction(async (transaction) => { try { const amount = orderItem.amount * (1 - paymentOptions.refundFeeRate); if (!refundResult) { refundResult = await delegate.partRefund(order.currency, amount, order, orderItem, paymentOptions); } // stock const tasks = []; const productID = orderItem.product; const skuID = orderItem.sku; if (orderItem.type === index_1.OrderItemType.sku) { if (!skuID) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid order ORDER/${order.id}, This order item is sku required.`); } // const tradeInformation: TradeInformation = { // selledBy: order.selledBy, // purchasedBy: order.purchasedBy, // order: order.id, // sku: skuID, // product: productID, // metadata: paymentOptions.metadata // } orderItem.status = index_1.OrderItemStatus.changed; const task = this.stockManager.itemCancel(order, orderItem, item, transaction); tasks.push(task); } const stockTransactions = await Promise.all(tasks); const tradeTransactions = await Promise.all(stockTransactions.map(stockTransaction => stockTransaction.commit())); // payment const balanceTransaction = this.balanceManager.refund(order.purchasedBy, order.id, order.currency, amount, { [paymentOptions.vendorType]: refundResult }, transaction); this.orderManager.update(order, {}, { [paymentOptions.vendorType]: refundResult }, transaction); return ({ tradeTransactions: tradeTransactions, balanceTransaction: balanceTransaction, refundResult: refundResult }); } catch (error) { if (refundResult) { throw ({ refundResult: refundResult }); } else { throw error; } } }); } catch (error) { if (error instanceof index_1.TradableError) { throw error; } let CheckoutCancelResult = error; return CheckoutCancelResult; } } } catch (error) { throw error; } } async transfer(order, transferOptions) { try { const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, Manager required delegate.`); } if (order.isCancelled) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, This order is Cancelled`); } if (!(order.paymentStatus === index_1.OrderPaymentStatus.paid)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, This order paymentStatus is invalid.`); } if (!(order.transferStatus === index_1.OrderTransferStatus.none)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, This order transferStatus is invalid.`); } if (order.amount === 0) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, This order is zero amount.`); } else { let transferResult = undefined; const amount = order.amount * (1 - transferOptions.transferRate); try { return await index_1.firestore.runTransaction(async (transaction) => { return new Promise(async (resolve, reject) => { try { if (!transferResult) { const to = new this._Account(order.selledBy, {}); await to.fetch(transaction); transferResult = await delegate.transfer(order.currency, amount, order, to, transferOptions); } // transfer const balanceTransaction = await this.balanceManager.transfer(balanceManager_1.BalanceManager.platform, order.selledBy, order.id, order.currency, amount, { [transferOptions.vendorType]: transferResult }, transaction); order.transferStatus = index_1.OrderTransferStatus.transferred; this.orderManager.update(order, [], { [transferOptions.vendorType]: transferResult }, transaction); const result = { balanceTransaction: balanceTransaction, transferResult: transferResult }; resolve(result); } catch (error) { if (transferResult) { reject({ transferResult: transferResult }); } else { reject(error); } } }); }); } catch (error) { if (error instanceof index_1.TradableError) { order.transferStatus = index_1.OrderTransferStatus.transferFailure; try { await order.update(); } catch (error) { throw error; } throw error; } let transferResult = error; try { if (transferResult.transferResult) { const transferCancelResult = await delegate.transferCancel(order.currency, amount, order, transferOptions, `[Manager] Invalid transfer ORDER/${order.id}, transaction failure.`); transferResult.transferCancelResult = transferCancelResult; } throw transferResult; } catch (error) { order.transferStatus = index_1.OrderTransferStatus.transferFailure; try { await order.update(); } catch (error) { throw error; } throw error; } } } } catch (error) { throw error; } } async transferCancel(order, transferOptions) { try { const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, Manager required delegate.`); } if (!(order.paymentStatus === index_1.OrderPaymentStatus.paid)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, This order paymentStatus is invalid.`); } if (!(order.transferStatus === index_1.OrderTransferStatus.transferred)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, This order transferStatus is invalid.`); } if (order.amount === 0) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid transfer ORDER/${order.id}, This order is zero amount.`); } else { const amount = order.amount * (1 - transferOptions.transferRate); const transferCancelResult = await delegate.transferCancel(order.currency, amount, order, transferOptions); try { await index_1.firestore.runTransaction(async (transaction) => { return new Promise(async (resolve, reject) => { // transfer const balanceTransaction = await this.balanceManager.transferRefund(balanceManager_1.BalanceManager.platform, order.selledBy, order.id, order.currency, amount, { [transferOptions.vendorType]: transferCancelResult }, transaction); order.transferStatus = index_1.OrderTransferStatus.cancelled; this.orderManager.update(order, [], { [transferOptions.vendorType]: transferCancelResult }, transaction); const result = { balanceTransaction: balanceTransaction, transferCancelResult: transferCancelResult }; resolve(result); }); }); } catch (error) { order.transferStatus = index_1.OrderTransferStatus.transferFailure; try { await order.update(); } catch (error) { throw error; } throw error; } } } catch (error) { throw error; } } async request(payout, payoutOptions) { try { if (payout.amount === 0) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid payout ACCOUNT/${payout.account}, This payout is zero amount.`); } try { await index_1.firestore.runTransaction(async (transaction) => { payout.status = index_1.PayoutStatus.requested; this.payoutManager.update(payout, {}, transaction); return; }); } catch (error) { throw error; } } catch (error) { throw error; } } async payout(payout, payoutOptions) { try { if (!(payout.status === index_1.PayoutStatus.requested)) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid payout Payout/${payout.id}, This payout status is invalid.`); } const delegate = this.delegate; if (!delegate) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid payout ACCOUNT/${payout.account}, Manager required delegate.`); } if (payout.amount === 0) { throw new index_1.TradableError(index_1.TradableErrorCode.invalidArgument, `[Manager] Invalid payout ACCOUNT/${payout.account}, This order is zero amount.`); } const currency = payout.currency; const amount = payout.amount; const accountID = payout.account; const result = await delegate.payout(currency, amount, accountID, payoutOptions); try { await index_1.firestore.runTransaction(async (transaction) => { return new Promise(async (resolve, reject) => { // payout const balanceTransaction = await this.balanceManager.payout(accountID, currency, amount, result, transaction); payout.status = index_1.PayoutStatus.completed; this.payoutManager.update(payout, { [payoutOptions.vendorType]: result }, transaction); const payoutResult = { balanceTransaction: balanceTransaction, payoutResult: result }; resolve(payoutResult); }); }); } catch (error) { try { await delegate.payoutCancel(currency, amount, accountID, payoutOptions); } catch (error) { throw error; } throw error; } } catch (error) { throw error; } } async payoutCancel(accountID, currency, amount, payoutOptions) { try { const delegate = this.delegate; if (!delegate) { t