-
Notifications
You must be signed in to change notification settings - Fork 16
/
allocation.ts
137 lines (128 loc) · 4.42 KB
/
allocation.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { Allocation as Model, MarketDecoration } from "ya-ts-client/dist/ya-payment";
import { AllocationConfig, BasePaymentOptions } from "./config";
import { Allocation as AllocationModel } from "ya-ts-client/dist/ya-payment/src/models/allocation";
import { Events } from "../events";
/**
* @category Mid-level
*/
export interface AllocationOptions extends BasePaymentOptions {
account: { address: string; platform: string };
expires?: number;
}
/**
* Allocation module - an object represents a designated sum of money reserved for the purpose of making some particular payments. Allocations are currently purely virtual objects. An Allocation is connected to a payment account (wallet) specified by address and payment platform field.
* @category Mid-level
*/
export class Allocation {
/** Allocation ID */
public readonly id: string;
/** Timestamp of creation */
public readonly timestamp: string;
/** Timeout */
public readonly timeout?: string;
/** Address of requestor */
public readonly address: string;
/** Payment platform */
public readonly paymentPlatform: string;
/** Total allocation Amount */
public readonly totalAmount: string;
private spentAmount: string;
private remainingAmount: string;
/**
* Create allocation
*
* @param options - {@link AllocationOptions}
*/
static async create(options: AllocationOptions): Promise<Allocation> {
const config = new AllocationConfig(options);
const now = new Date();
const model: AllocationModel = {
totalAmount: config.budget.toString(),
paymentPlatform: config.account.platform,
address: config.account.address,
timestamp: now.toISOString(),
timeout: new Date(+now + config.expires).toISOString(),
makeDeposit: false,
remainingAmount: "",
spentAmount: "",
allocationId: "",
};
const { data: newModel } = await config.api.createAllocation(model).catch((error) => {
throw new Error(
`Could not create new allocation. ${error.response?.data?.message || error.response?.data || error}`
);
});
config.eventTarget?.dispatchEvent(
new Events.AllocationCreated({
id: newModel.allocationId,
amount: parseFloat(newModel.totalAmount),
platform: newModel.paymentPlatform,
})
);
config.logger?.debug(
`Allocation ${newModel.allocationId} has been created using payment platform ${config.account.platform}`
);
return new Allocation(config, newModel);
}
/**
* @param options - {@link AllocationConfig}
* @param model - {@link Model}
* @hidden
*/
constructor(private options: AllocationConfig, model: Model) {
this.id = model.allocationId;
this.timeout = model.timeout;
this.timestamp = model.timestamp;
this.totalAmount = model.totalAmount;
this.spentAmount = model.spentAmount;
this.remainingAmount = model.remainingAmount;
if (!model.address || !model.paymentPlatform) throw new Error("Account address and payment platform are required");
this.address = model.address;
this.paymentPlatform = model.paymentPlatform;
}
/**
* Returns remaining amount for allocation
*
* @return amount remaining
*/
async getRemainingAmount(): Promise<string> {
await this.refresh();
return this.remainingAmount;
}
/**
* Returns already spent amount for allocation
*
* @return spent amount
*/
async getSpentAmount(): Promise<string> {
await this.refresh();
return this.spentAmount;
}
/**
* Release allocation
*/
async release() {
await this.options.api.releaseAllocation(this.id).catch((e) => {
throw new Error(`Could not release allocation. ${e.response?.data?.message || e}`);
});
this.options?.logger?.debug(`Allocation ${this.id} has been released.`);
}
/**
* Returns Market ya-ts-client decoration
*
* @return {@link MarketDecoration}
*/
async getDemandDecoration(): Promise<MarketDecoration> {
const { data: decoration } = await this.options.api.getDemandDecorations([this.id]).catch((e) => {
throw new Error(`Unable to get demand decorations. ${e.response?.data?.message || e}`);
});
return decoration;
}
private async refresh() {
const { data } = await this.options.api.getAllocation(this.id).catch((e) => {
throw new Error(`Could not get allocation data. ${e.response?.data || e}`);
});
this.remainingAmount = data.remainingAmount;
this.spentAmount = data.spentAmount;
}
}