import { LTOApi } from "./api" import { v4 as uuidv4 } from 'uuid'; import { RefStore } from "../../state/state"; import { debug } from "loglevel"; export const TxnStates = ["PENDING","INFLIGHT","WORKING","ERROR","SUCCESS"] as const export type TxnState = typeof TxnStates[number] export interface TxnDetails { item_uid: string | "galders" count:number origin:string target:string origin_path:string target_path:string } export abstract class Order { action_id: string details?:TxnDetails created:Date state: TxnState constructor(details?:TxnDetails) { this.state = "PENDING" this.details = details this.created = new Date() this.action_id = uuidv4(); } mark(t:TxnState) { this.state = t } abstract tick(r:RefStore, api:LTOApi):Promise abstract status():string abstract progress():[number, number] abstract error():string abstract order_type:OrderType parse(i:any):Order { this.action_id = i.action_id this.details = i.details this.created = new Date(i.created) this.state = i.state return this } } export abstract class BasicOrder extends Order { stage: number err?: string constructor(details:TxnDetails) { super(details) this.stage = 0 } progress():[number,number]{ return [this.stage, 1] } status():string { return this.state } error():string { return this.err ? this.err : "" } parse(i:any):BasicOrder { this.stage = i.stage this.err = i.err super.parse(i) return this } } /// start user defined export const OrderTypes = ["InvalidOrder","BankItem","InternalXfer"] export type OrderType = typeof OrderTypes[number] export class InvalidOrder extends Order{ order_type = "InvalidOrder" msg:string constructor(msg: string){ super(undefined) this.msg = msg this.mark("ERROR") } status():string { return "ERROR" } progress():[number, number] { return [0,0] } error(): string { return this.msg } async tick(r:RefStore, api:LTOApi):Promise { return } parse(i:any):InvalidOrder { super.parse(i) this.msg = i.msg return this } } export interface BasicResponse { status: number data: any msg?: string } export interface InternalXferRequest { item_uid:string qty:string account:string new_char:string } export interface InternalXferResponse extends BasicResponse {} export class InternalXfer extends BasicOrder{ order_type = "InternalXfer" originalRequest:InternalXferRequest originalResponse?:InternalXferResponse constructor(details:TxnDetails) { super(details) this.originalRequest = { item_uid: details.item_uid, qty: details.count.toString(), new_char: details.target, account: details.origin, } } async tick(r:RefStore, api:LTOApi):Promise { if(this.state !== "PENDING") { return } this.mark("WORKING") return api.BankAction("internal-xfer-item",this.originalRequest) .then((x:InternalXferResponse)=>{ if(x.status == 200){ this.originalResponse = x this.stage = 1 this.mark("SUCCESS") const origin_item = r.invs.value.get(this.details?.origin_path!)!.items[this.details?.item_uid!]! origin_item.item_count = origin_item.item_count - this.details?.count! r.dirty.value++ }else{ throw x.msg } }) .catch((e)=>{ debug("InternalXfer",e) this.stage = 1 this.err = e this.mark("ERROR") }) } parse(i:any):InternalXfer { super.parse(i) this.originalRequest = i.originalRequest this.originalResponse = i.originalResponse return this } } export interface BankItemRequest { item_uid:string qty:string account:string } export interface BankItemResponse extends BasicResponse {} export class BankItem extends BasicOrder{ order_type = "BankItem"; originalRequest:BankItemRequest originalResponse?:BankItemResponse constructor(details:TxnDetails) { super(details) this.originalRequest = { item_uid: details.item_uid, qty: details.count.toString(), account: details.target, } } async tick(r:RefStore, api:LTOApi):Promise { if(this.state !== "PENDING" ){ return } this.mark("WORKING") return api.BankAction("bank-item",this.originalRequest) .then((x)=>{ debug("BankItem",x) if(x.status == 200){ this.stage = 1 this.originalResponse = x this.mark("SUCCESS") const origin_item = r.invs.value.get(this.details?.origin_path!)!.items[this.details?.item_uid!]! origin_item.item_count = origin_item.item_count - this.details?.count! r.dirty.value++ }else { throw x.msg ? "unknown error" : "" } }) .catch((e)=>{ this.stage = 1 this.err = e this.mark("ERROR") }) } parse(i:any):BankItem { super.parse(i) this.originalRequest = i.originalRequest this.originalResponse = i.originalResponse return this } }