-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathamm.ts
88 lines (73 loc) · 3.2 KB
/
amm.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
import { BondingCurveAccount } from "./bondingCurveAccount";
import { GlobalAccount } from "./globalAccount";
export type BuyResult = {
token_amount: bigint;
sol_amount: bigint;
};
export type SellResult = {
token_amount: bigint;
sol_amount: bigint;
};
export class AMM {
constructor(
public virtualSolReserves: bigint,
public virtualTokenReserves: bigint,
public realSolReserves: bigint,
public realTokenReserves: bigint,
public initialVirtualTokenReserves: bigint
) {}
static fromGlobalAccount(global: GlobalAccount): AMM {
return new AMM(
global.initialVirtualSolReserves,
global.initialVirtualTokenReserves,
0n,
global.initialRealTokenReserves,
global.initialVirtualTokenReserves
);
}
static fromBondingCurveAccount(bonding_curve: BondingCurveAccount, initialVirtualTokenReserves: bigint): AMM {
return new AMM(
bonding_curve.virtualSolReserves,
bonding_curve.virtualTokenReserves,
bonding_curve.realSolReserves,
bonding_curve.realTokenReserves,
initialVirtualTokenReserves
);
}
getBuyPrice(tokens: bigint): bigint {
const product_of_reserves = this.virtualSolReserves * this.virtualTokenReserves;
const new_virtual_token_reserves = this.virtualTokenReserves - tokens;
const new_virtual_sol_reserves = product_of_reserves / new_virtual_token_reserves + 1n;
const amount_needed = new_virtual_sol_reserves > this.virtualSolReserves ? new_virtual_sol_reserves - this.virtualSolReserves : 0n;
return amount_needed > 0n ? amount_needed : 0n;
}
applyBuy(token_amount: bigint): BuyResult {
const final_token_amount = token_amount > this.realTokenReserves ? this.realTokenReserves : token_amount;
const sol_amount = this.getBuyPrice(final_token_amount);
this.virtualTokenReserves = this.virtualTokenReserves - final_token_amount;
this.realTokenReserves = this.realTokenReserves - final_token_amount;
this.virtualSolReserves = this.virtualSolReserves + sol_amount;
this.realSolReserves = this.realSolReserves + sol_amount;
return {
token_amount: final_token_amount,
sol_amount: sol_amount
}
}
applySell(token_amount: bigint): SellResult {
this.virtualTokenReserves = this.virtualTokenReserves + token_amount;
this.realTokenReserves = this.realTokenReserves + token_amount;
const sell_price = this.getSellPrice(token_amount);
this.virtualSolReserves = this.virtualSolReserves - sell_price;
this.realSolReserves = this.realSolReserves - sell_price;
return {
token_amount: token_amount,
sol_amount: sell_price
}
}
getSellPrice(tokens: bigint): bigint {
const scaling_factor = this.initialVirtualTokenReserves;
const token_sell_proportion = (tokens * scaling_factor) / this.virtualTokenReserves;
const sol_received = (this.virtualSolReserves * token_sell_proportion) / scaling_factor;
return sol_received < this.realSolReserves ? sol_received : this.realSolReserves;
}
}