@ocap/util 1.21.3 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/curve.d.ts +85 -0
- package/esm/curve.js +146 -0
- package/lib/curve.d.ts +85 -0
- package/lib/curve.js +157 -0
- package/package.json +3 -2
package/esm/curve.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { BN } from './index';
|
|
2
|
+
declare enum Direction {
|
|
3
|
+
Mint = "mint",
|
|
4
|
+
Burn = "burn"
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Constant Curve
|
|
8
|
+
* Price = fixedPrice
|
|
9
|
+
*/
|
|
10
|
+
export declare function calcConstantPrice({ fixedPrice }: {
|
|
11
|
+
fixedPrice: string;
|
|
12
|
+
}): BN;
|
|
13
|
+
/**
|
|
14
|
+
* Constant Curve
|
|
15
|
+
* Cost = amount * fixedPrice
|
|
16
|
+
*/
|
|
17
|
+
export declare function calcConstantCost({ amount, fixedPrice, decimal, }: {
|
|
18
|
+
amount: string;
|
|
19
|
+
fixedPrice: string;
|
|
20
|
+
decimal: number;
|
|
21
|
+
}): BN;
|
|
22
|
+
/**
|
|
23
|
+
* linear Curve
|
|
24
|
+
* Price = basePrice + slope * currentSupply
|
|
25
|
+
*/
|
|
26
|
+
export declare function calcLinearPrice({ basePrice, slope, currentSupply, decimal, }: {
|
|
27
|
+
basePrice: string;
|
|
28
|
+
slope: string;
|
|
29
|
+
currentSupply: string;
|
|
30
|
+
decimal: number;
|
|
31
|
+
}): BN;
|
|
32
|
+
/**
|
|
33
|
+
* Linear Curve
|
|
34
|
+
* mint Cost = (slope / 2) * ( (currentSupply + amount) ** 2 - currentSupply ** 2 ) + basePrice * amount;
|
|
35
|
+
* burn Cost = (slope / 2) * ( currentSupply ** 2 - (currentSupply - amount) ** 2 ) + basePrice * amount;
|
|
36
|
+
*/
|
|
37
|
+
export declare function calcLinearCost(params: {
|
|
38
|
+
amount: string;
|
|
39
|
+
currentSupply: string;
|
|
40
|
+
basePrice: string;
|
|
41
|
+
slope: string;
|
|
42
|
+
decimal: number;
|
|
43
|
+
direction: Direction;
|
|
44
|
+
}): BN;
|
|
45
|
+
/**
|
|
46
|
+
* Quadratic Curve
|
|
47
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
48
|
+
*/
|
|
49
|
+
export declare function calcQuadraticPrice(params: {
|
|
50
|
+
basePrice: string;
|
|
51
|
+
currentSupply: string;
|
|
52
|
+
constant: string;
|
|
53
|
+
decimal: number;
|
|
54
|
+
}): BN;
|
|
55
|
+
/**
|
|
56
|
+
* Quadratic Curve
|
|
57
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
58
|
+
* mint Cost = ( (currentSupply + amount)^3 / 3 - currentSupply^3 / 3 ) / constant + basePrice * amount;
|
|
59
|
+
* burn Cost = ( currentSupply^3 / 3 - (currentSupply - amount)^3 / 3 ) / constant + basePrice * amount;
|
|
60
|
+
*/
|
|
61
|
+
export declare function calcQuadraticCost(params: {
|
|
62
|
+
amount: string;
|
|
63
|
+
currentSupply: string;
|
|
64
|
+
basePrice: string;
|
|
65
|
+
constant: string;
|
|
66
|
+
decimal: number;
|
|
67
|
+
direction: Direction;
|
|
68
|
+
}): BN;
|
|
69
|
+
export declare function calcFee({ reserveAmount, feeRate }: {
|
|
70
|
+
reserveAmount: string;
|
|
71
|
+
feeRate: string;
|
|
72
|
+
}): BN;
|
|
73
|
+
export declare function calcPrice({ currentSupply, decimal, curve }: {
|
|
74
|
+
currentSupply: string;
|
|
75
|
+
decimal: number;
|
|
76
|
+
curve: any;
|
|
77
|
+
}): BN;
|
|
78
|
+
export declare function calcCost({ amount, decimal, currentSupply, direction, curve, }: {
|
|
79
|
+
amount: string;
|
|
80
|
+
decimal: number;
|
|
81
|
+
currentSupply: string;
|
|
82
|
+
curve: any;
|
|
83
|
+
direction: Direction;
|
|
84
|
+
}): BN;
|
|
85
|
+
export {};
|
package/esm/curve.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { BN } from './index';
|
|
2
|
+
const ZERO = new BN(0);
|
|
3
|
+
const TWO = new BN(2);
|
|
4
|
+
const THREE = new BN(3);
|
|
5
|
+
const TEN = new BN(10);
|
|
6
|
+
var Direction;
|
|
7
|
+
(function (Direction) {
|
|
8
|
+
Direction["Mint"] = "mint";
|
|
9
|
+
Direction["Burn"] = "burn";
|
|
10
|
+
})(Direction || (Direction = {}));
|
|
11
|
+
/**
|
|
12
|
+
* Constant Curve
|
|
13
|
+
* Price = fixedPrice
|
|
14
|
+
*/
|
|
15
|
+
export function calcConstantPrice({ fixedPrice }) {
|
|
16
|
+
return new BN(fixedPrice);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Constant Curve
|
|
20
|
+
* Cost = amount * fixedPrice
|
|
21
|
+
*/
|
|
22
|
+
export function calcConstantCost({ amount, fixedPrice, decimal, }) {
|
|
23
|
+
const decimalFactor = TEN.pow(new BN(decimal));
|
|
24
|
+
return new BN(amount).mul(new BN(fixedPrice)).div(decimalFactor);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* linear Curve
|
|
28
|
+
* Price = basePrice + slope * currentSupply
|
|
29
|
+
*/
|
|
30
|
+
export function calcLinearPrice({ basePrice, slope, currentSupply, decimal, }) {
|
|
31
|
+
const decimalFactor = TEN.pow(new BN(decimal));
|
|
32
|
+
return new BN(basePrice).add(new BN(slope).mul(new BN(currentSupply)).div(decimalFactor));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Linear Curve
|
|
36
|
+
* mint Cost = (slope / 2) * ( (currentSupply + amount) ** 2 - currentSupply ** 2 ) + basePrice * amount;
|
|
37
|
+
* burn Cost = (slope / 2) * ( currentSupply ** 2 - (currentSupply - amount) ** 2 ) + basePrice * amount;
|
|
38
|
+
*/
|
|
39
|
+
export function calcLinearCost(params) {
|
|
40
|
+
const amount = new BN(params.amount);
|
|
41
|
+
const currentSupply = new BN(params.currentSupply);
|
|
42
|
+
const basePrice = new BN(params.basePrice);
|
|
43
|
+
const slope = new BN(params.slope);
|
|
44
|
+
const decimalFactor = TEN.pow(new BN(params.decimal));
|
|
45
|
+
if (slope.lte(ZERO))
|
|
46
|
+
throw new Error('INVALID_SLOPE');
|
|
47
|
+
if (amount.lt(ZERO))
|
|
48
|
+
throw new Error('INVALID_AMOUNT');
|
|
49
|
+
if (currentSupply.lt(ZERO))
|
|
50
|
+
throw new Error('INVALID_CURRENT_SUPPLY');
|
|
51
|
+
if (basePrice.lt(ZERO))
|
|
52
|
+
throw new Error('INVALID_BASE_PRICE');
|
|
53
|
+
if (decimalFactor.lte(ZERO))
|
|
54
|
+
throw new Error('INVALID_DECIMAL_FACTOR');
|
|
55
|
+
if (params.direction === Direction.Burn && amount.gt(currentSupply)) {
|
|
56
|
+
throw new Error('SUPPLY_INSUFFICIENT');
|
|
57
|
+
}
|
|
58
|
+
const integralDelta = params.direction === Direction.Mint
|
|
59
|
+
? amount.mul(currentSupply.mul(TWO).add(amount)) // (currentSupply + amount) ** 2 - currentSupply ** 2 = amount * (2 * currentSupply + amount)
|
|
60
|
+
: amount.mul(currentSupply.mul(TWO).sub(amount)); // currentSupply ** 2 - (currentSupply - amount) ** 2 = amount * (2 * currentSupply - amount)
|
|
61
|
+
const linearTerm = basePrice.mul(amount).div(decimalFactor);
|
|
62
|
+
const integralTerm = slope.mul(integralDelta).div(TWO.mul(decimalFactor.sqr()));
|
|
63
|
+
return linearTerm.add(integralTerm);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Quadratic Curve
|
|
67
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
68
|
+
*/
|
|
69
|
+
export function calcQuadraticPrice(params) {
|
|
70
|
+
const basePrice = new BN(params.basePrice);
|
|
71
|
+
const currentSupply = new BN(params.currentSupply);
|
|
72
|
+
const constant = new BN(params.constant);
|
|
73
|
+
const decimalFactor = TEN.pow(new BN(params.decimal)); // 10^decimal
|
|
74
|
+
if (constant.lte(ZERO))
|
|
75
|
+
throw new Error('INVALID_CONSTANT');
|
|
76
|
+
if (currentSupply.lt(ZERO))
|
|
77
|
+
throw new Error('INVALID_CURRENT_SUPPLY');
|
|
78
|
+
if (basePrice.lt(ZERO))
|
|
79
|
+
throw new Error('INVALID_BASE_PRICE');
|
|
80
|
+
if (decimalFactor.lte(ZERO))
|
|
81
|
+
throw new Error('INVALID_DECIMAL_FACTOR');
|
|
82
|
+
// Single division to reduce double-flooring error
|
|
83
|
+
const denom = constant.mul(decimalFactor);
|
|
84
|
+
const a = currentSupply.sqr().div(denom);
|
|
85
|
+
return basePrice.add(a);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Quadratic Curve
|
|
89
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
90
|
+
* mint Cost = ( (currentSupply + amount)^3 / 3 - currentSupply^3 / 3 ) / constant + basePrice * amount;
|
|
91
|
+
* burn Cost = ( currentSupply^3 / 3 - (currentSupply - amount)^3 / 3 ) / constant + basePrice * amount;
|
|
92
|
+
*/
|
|
93
|
+
export function calcQuadraticCost(params) {
|
|
94
|
+
const amount = new BN(params.amount);
|
|
95
|
+
const currentSupply = new BN(params.currentSupply);
|
|
96
|
+
const basePrice = new BN(params.basePrice);
|
|
97
|
+
const constant = new BN(params.constant);
|
|
98
|
+
const decimalFactor = TEN.pow(new BN(params.decimal)); // M = 10^decimal
|
|
99
|
+
// Basic validations
|
|
100
|
+
if (constant.lte(ZERO))
|
|
101
|
+
throw new Error('INVALID_CONSTANT');
|
|
102
|
+
if (amount.lt(ZERO))
|
|
103
|
+
throw new Error('INVALID_AMOUNT');
|
|
104
|
+
if (amount.isZero())
|
|
105
|
+
return ZERO;
|
|
106
|
+
// Compute new supply with direction guard
|
|
107
|
+
const newSupply = params.direction === Direction.Mint ? currentSupply.add(amount) : currentSupply.sub(amount);
|
|
108
|
+
if (params.direction === Direction.Burn && newSupply.lt(ZERO)) {
|
|
109
|
+
throw new Error('SUPPLY_INSUFFICIENT');
|
|
110
|
+
}
|
|
111
|
+
// cubicDelta = |S1^3 - S0^3| = (S1 - S0) * (S1^2 + S1 * S0 + S0^2)
|
|
112
|
+
const diff = params.direction === Direction.Mint ? newSupply.sub(currentSupply) : currentSupply.sub(newSupply);
|
|
113
|
+
const sumSquaresAndProduct = newSupply.sqr().add(newSupply.mul(currentSupply)).add(currentSupply.sqr());
|
|
114
|
+
const cubicDelta = diff.mul(sumSquaresAndProduct);
|
|
115
|
+
// integral term: (S1^3 - S0^3) / (3 * constant * M^2)
|
|
116
|
+
const denom = THREE.mul(constant).mul(decimalFactor.sqr());
|
|
117
|
+
const cubicCost = cubicDelta.div(denom);
|
|
118
|
+
// linear term: basePrice * amount / M
|
|
119
|
+
const linearCost = basePrice.mul(amount).div(decimalFactor);
|
|
120
|
+
return cubicCost.add(linearCost);
|
|
121
|
+
}
|
|
122
|
+
export function calcFee({ reserveAmount, feeRate }) {
|
|
123
|
+
return new BN(reserveAmount).mul(new BN(feeRate)).div(new BN(10000));
|
|
124
|
+
}
|
|
125
|
+
export function calcPrice({ currentSupply, decimal, curve }) {
|
|
126
|
+
const calculator = {
|
|
127
|
+
constant: () => calcConstantPrice({ currentSupply, decimal, ...curve }),
|
|
128
|
+
linear: () => calcLinearPrice({ currentSupply, decimal, ...curve }),
|
|
129
|
+
quadratic: () => calcQuadraticPrice({ currentSupply, decimal, ...curve }),
|
|
130
|
+
}[curve.type];
|
|
131
|
+
if (!calculator) {
|
|
132
|
+
throw new Error('INVALID_CURVE_TYPE');
|
|
133
|
+
}
|
|
134
|
+
return calculator();
|
|
135
|
+
}
|
|
136
|
+
export function calcCost({ amount, decimal, currentSupply, direction, curve, }) {
|
|
137
|
+
const calculator = {
|
|
138
|
+
constant: () => calcConstantCost({ amount, decimal, ...curve }),
|
|
139
|
+
linear: () => calcLinearCost({ amount, decimal, currentSupply, direction, ...curve }),
|
|
140
|
+
quadratic: () => calcQuadraticCost({ amount, decimal, currentSupply, direction, ...curve }),
|
|
141
|
+
}[curve.type];
|
|
142
|
+
if (!calculator) {
|
|
143
|
+
throw new Error('INVALID_CURVE_TYPE');
|
|
144
|
+
}
|
|
145
|
+
return calculator();
|
|
146
|
+
}
|
package/lib/curve.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { BN } from './index';
|
|
2
|
+
declare enum Direction {
|
|
3
|
+
Mint = "mint",
|
|
4
|
+
Burn = "burn"
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Constant Curve
|
|
8
|
+
* Price = fixedPrice
|
|
9
|
+
*/
|
|
10
|
+
export declare function calcConstantPrice({ fixedPrice }: {
|
|
11
|
+
fixedPrice: string;
|
|
12
|
+
}): BN;
|
|
13
|
+
/**
|
|
14
|
+
* Constant Curve
|
|
15
|
+
* Cost = amount * fixedPrice
|
|
16
|
+
*/
|
|
17
|
+
export declare function calcConstantCost({ amount, fixedPrice, decimal, }: {
|
|
18
|
+
amount: string;
|
|
19
|
+
fixedPrice: string;
|
|
20
|
+
decimal: number;
|
|
21
|
+
}): BN;
|
|
22
|
+
/**
|
|
23
|
+
* linear Curve
|
|
24
|
+
* Price = basePrice + slope * currentSupply
|
|
25
|
+
*/
|
|
26
|
+
export declare function calcLinearPrice({ basePrice, slope, currentSupply, decimal, }: {
|
|
27
|
+
basePrice: string;
|
|
28
|
+
slope: string;
|
|
29
|
+
currentSupply: string;
|
|
30
|
+
decimal: number;
|
|
31
|
+
}): BN;
|
|
32
|
+
/**
|
|
33
|
+
* Linear Curve
|
|
34
|
+
* mint Cost = (slope / 2) * ( (currentSupply + amount) ** 2 - currentSupply ** 2 ) + basePrice * amount;
|
|
35
|
+
* burn Cost = (slope / 2) * ( currentSupply ** 2 - (currentSupply - amount) ** 2 ) + basePrice * amount;
|
|
36
|
+
*/
|
|
37
|
+
export declare function calcLinearCost(params: {
|
|
38
|
+
amount: string;
|
|
39
|
+
currentSupply: string;
|
|
40
|
+
basePrice: string;
|
|
41
|
+
slope: string;
|
|
42
|
+
decimal: number;
|
|
43
|
+
direction: Direction;
|
|
44
|
+
}): BN;
|
|
45
|
+
/**
|
|
46
|
+
* Quadratic Curve
|
|
47
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
48
|
+
*/
|
|
49
|
+
export declare function calcQuadraticPrice(params: {
|
|
50
|
+
basePrice: string;
|
|
51
|
+
currentSupply: string;
|
|
52
|
+
constant: string;
|
|
53
|
+
decimal: number;
|
|
54
|
+
}): BN;
|
|
55
|
+
/**
|
|
56
|
+
* Quadratic Curve
|
|
57
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
58
|
+
* mint Cost = ( (currentSupply + amount)^3 / 3 - currentSupply^3 / 3 ) / constant + basePrice * amount;
|
|
59
|
+
* burn Cost = ( currentSupply^3 / 3 - (currentSupply - amount)^3 / 3 ) / constant + basePrice * amount;
|
|
60
|
+
*/
|
|
61
|
+
export declare function calcQuadraticCost(params: {
|
|
62
|
+
amount: string;
|
|
63
|
+
currentSupply: string;
|
|
64
|
+
basePrice: string;
|
|
65
|
+
constant: string;
|
|
66
|
+
decimal: number;
|
|
67
|
+
direction: Direction;
|
|
68
|
+
}): BN;
|
|
69
|
+
export declare function calcFee({ reserveAmount, feeRate }: {
|
|
70
|
+
reserveAmount: string;
|
|
71
|
+
feeRate: string;
|
|
72
|
+
}): BN;
|
|
73
|
+
export declare function calcPrice({ currentSupply, decimal, curve }: {
|
|
74
|
+
currentSupply: string;
|
|
75
|
+
decimal: number;
|
|
76
|
+
curve: any;
|
|
77
|
+
}): BN;
|
|
78
|
+
export declare function calcCost({ amount, decimal, currentSupply, direction, curve, }: {
|
|
79
|
+
amount: string;
|
|
80
|
+
decimal: number;
|
|
81
|
+
currentSupply: string;
|
|
82
|
+
curve: any;
|
|
83
|
+
direction: Direction;
|
|
84
|
+
}): BN;
|
|
85
|
+
export {};
|
package/lib/curve.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calcConstantPrice = calcConstantPrice;
|
|
4
|
+
exports.calcConstantCost = calcConstantCost;
|
|
5
|
+
exports.calcLinearPrice = calcLinearPrice;
|
|
6
|
+
exports.calcLinearCost = calcLinearCost;
|
|
7
|
+
exports.calcQuadraticPrice = calcQuadraticPrice;
|
|
8
|
+
exports.calcQuadraticCost = calcQuadraticCost;
|
|
9
|
+
exports.calcFee = calcFee;
|
|
10
|
+
exports.calcPrice = calcPrice;
|
|
11
|
+
exports.calcCost = calcCost;
|
|
12
|
+
const index_1 = require("./index");
|
|
13
|
+
const ZERO = new index_1.BN(0);
|
|
14
|
+
const TWO = new index_1.BN(2);
|
|
15
|
+
const THREE = new index_1.BN(3);
|
|
16
|
+
const TEN = new index_1.BN(10);
|
|
17
|
+
var Direction;
|
|
18
|
+
(function (Direction) {
|
|
19
|
+
Direction["Mint"] = "mint";
|
|
20
|
+
Direction["Burn"] = "burn";
|
|
21
|
+
})(Direction || (Direction = {}));
|
|
22
|
+
/**
|
|
23
|
+
* Constant Curve
|
|
24
|
+
* Price = fixedPrice
|
|
25
|
+
*/
|
|
26
|
+
function calcConstantPrice({ fixedPrice }) {
|
|
27
|
+
return new index_1.BN(fixedPrice);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Constant Curve
|
|
31
|
+
* Cost = amount * fixedPrice
|
|
32
|
+
*/
|
|
33
|
+
function calcConstantCost({ amount, fixedPrice, decimal, }) {
|
|
34
|
+
const decimalFactor = TEN.pow(new index_1.BN(decimal));
|
|
35
|
+
return new index_1.BN(amount).mul(new index_1.BN(fixedPrice)).div(decimalFactor);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* linear Curve
|
|
39
|
+
* Price = basePrice + slope * currentSupply
|
|
40
|
+
*/
|
|
41
|
+
function calcLinearPrice({ basePrice, slope, currentSupply, decimal, }) {
|
|
42
|
+
const decimalFactor = TEN.pow(new index_1.BN(decimal));
|
|
43
|
+
return new index_1.BN(basePrice).add(new index_1.BN(slope).mul(new index_1.BN(currentSupply)).div(decimalFactor));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Linear Curve
|
|
47
|
+
* mint Cost = (slope / 2) * ( (currentSupply + amount) ** 2 - currentSupply ** 2 ) + basePrice * amount;
|
|
48
|
+
* burn Cost = (slope / 2) * ( currentSupply ** 2 - (currentSupply - amount) ** 2 ) + basePrice * amount;
|
|
49
|
+
*/
|
|
50
|
+
function calcLinearCost(params) {
|
|
51
|
+
const amount = new index_1.BN(params.amount);
|
|
52
|
+
const currentSupply = new index_1.BN(params.currentSupply);
|
|
53
|
+
const basePrice = new index_1.BN(params.basePrice);
|
|
54
|
+
const slope = new index_1.BN(params.slope);
|
|
55
|
+
const decimalFactor = TEN.pow(new index_1.BN(params.decimal));
|
|
56
|
+
if (slope.lte(ZERO))
|
|
57
|
+
throw new Error('INVALID_SLOPE');
|
|
58
|
+
if (amount.lt(ZERO))
|
|
59
|
+
throw new Error('INVALID_AMOUNT');
|
|
60
|
+
if (currentSupply.lt(ZERO))
|
|
61
|
+
throw new Error('INVALID_CURRENT_SUPPLY');
|
|
62
|
+
if (basePrice.lt(ZERO))
|
|
63
|
+
throw new Error('INVALID_BASE_PRICE');
|
|
64
|
+
if (decimalFactor.lte(ZERO))
|
|
65
|
+
throw new Error('INVALID_DECIMAL_FACTOR');
|
|
66
|
+
if (params.direction === Direction.Burn && amount.gt(currentSupply)) {
|
|
67
|
+
throw new Error('SUPPLY_INSUFFICIENT');
|
|
68
|
+
}
|
|
69
|
+
const integralDelta = params.direction === Direction.Mint
|
|
70
|
+
? amount.mul(currentSupply.mul(TWO).add(amount)) // (currentSupply + amount) ** 2 - currentSupply ** 2 = amount * (2 * currentSupply + amount)
|
|
71
|
+
: amount.mul(currentSupply.mul(TWO).sub(amount)); // currentSupply ** 2 - (currentSupply - amount) ** 2 = amount * (2 * currentSupply - amount)
|
|
72
|
+
const linearTerm = basePrice.mul(amount).div(decimalFactor);
|
|
73
|
+
const integralTerm = slope.mul(integralDelta).div(TWO.mul(decimalFactor.sqr()));
|
|
74
|
+
return linearTerm.add(integralTerm);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Quadratic Curve
|
|
78
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
79
|
+
*/
|
|
80
|
+
function calcQuadraticPrice(params) {
|
|
81
|
+
const basePrice = new index_1.BN(params.basePrice);
|
|
82
|
+
const currentSupply = new index_1.BN(params.currentSupply);
|
|
83
|
+
const constant = new index_1.BN(params.constant);
|
|
84
|
+
const decimalFactor = TEN.pow(new index_1.BN(params.decimal)); // 10^decimal
|
|
85
|
+
if (constant.lte(ZERO))
|
|
86
|
+
throw new Error('INVALID_CONSTANT');
|
|
87
|
+
if (currentSupply.lt(ZERO))
|
|
88
|
+
throw new Error('INVALID_CURRENT_SUPPLY');
|
|
89
|
+
if (basePrice.lt(ZERO))
|
|
90
|
+
throw new Error('INVALID_BASE_PRICE');
|
|
91
|
+
if (decimalFactor.lte(ZERO))
|
|
92
|
+
throw new Error('INVALID_DECIMAL_FACTOR');
|
|
93
|
+
// Single division to reduce double-flooring error
|
|
94
|
+
const denom = constant.mul(decimalFactor);
|
|
95
|
+
const a = currentSupply.sqr().div(denom);
|
|
96
|
+
return basePrice.add(a);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Quadratic Curve
|
|
100
|
+
* Price = basePrice + currentSupply ** 2 / constant
|
|
101
|
+
* mint Cost = ( (currentSupply + amount)^3 / 3 - currentSupply^3 / 3 ) / constant + basePrice * amount;
|
|
102
|
+
* burn Cost = ( currentSupply^3 / 3 - (currentSupply - amount)^3 / 3 ) / constant + basePrice * amount;
|
|
103
|
+
*/
|
|
104
|
+
function calcQuadraticCost(params) {
|
|
105
|
+
const amount = new index_1.BN(params.amount);
|
|
106
|
+
const currentSupply = new index_1.BN(params.currentSupply);
|
|
107
|
+
const basePrice = new index_1.BN(params.basePrice);
|
|
108
|
+
const constant = new index_1.BN(params.constant);
|
|
109
|
+
const decimalFactor = TEN.pow(new index_1.BN(params.decimal)); // M = 10^decimal
|
|
110
|
+
// Basic validations
|
|
111
|
+
if (constant.lte(ZERO))
|
|
112
|
+
throw new Error('INVALID_CONSTANT');
|
|
113
|
+
if (amount.lt(ZERO))
|
|
114
|
+
throw new Error('INVALID_AMOUNT');
|
|
115
|
+
if (amount.isZero())
|
|
116
|
+
return ZERO;
|
|
117
|
+
// Compute new supply with direction guard
|
|
118
|
+
const newSupply = params.direction === Direction.Mint ? currentSupply.add(amount) : currentSupply.sub(amount);
|
|
119
|
+
if (params.direction === Direction.Burn && newSupply.lt(ZERO)) {
|
|
120
|
+
throw new Error('SUPPLY_INSUFFICIENT');
|
|
121
|
+
}
|
|
122
|
+
// cubicDelta = |S1^3 - S0^3| = (S1 - S0) * (S1^2 + S1 * S0 + S0^2)
|
|
123
|
+
const diff = params.direction === Direction.Mint ? newSupply.sub(currentSupply) : currentSupply.sub(newSupply);
|
|
124
|
+
const sumSquaresAndProduct = newSupply.sqr().add(newSupply.mul(currentSupply)).add(currentSupply.sqr());
|
|
125
|
+
const cubicDelta = diff.mul(sumSquaresAndProduct);
|
|
126
|
+
// integral term: (S1^3 - S0^3) / (3 * constant * M^2)
|
|
127
|
+
const denom = THREE.mul(constant).mul(decimalFactor.sqr());
|
|
128
|
+
const cubicCost = cubicDelta.div(denom);
|
|
129
|
+
// linear term: basePrice * amount / M
|
|
130
|
+
const linearCost = basePrice.mul(amount).div(decimalFactor);
|
|
131
|
+
return cubicCost.add(linearCost);
|
|
132
|
+
}
|
|
133
|
+
function calcFee({ reserveAmount, feeRate }) {
|
|
134
|
+
return new index_1.BN(reserveAmount).mul(new index_1.BN(feeRate)).div(new index_1.BN(10000));
|
|
135
|
+
}
|
|
136
|
+
function calcPrice({ currentSupply, decimal, curve }) {
|
|
137
|
+
const calculator = {
|
|
138
|
+
constant: () => calcConstantPrice({ currentSupply, decimal, ...curve }),
|
|
139
|
+
linear: () => calcLinearPrice({ currentSupply, decimal, ...curve }),
|
|
140
|
+
quadratic: () => calcQuadraticPrice({ currentSupply, decimal, ...curve }),
|
|
141
|
+
}[curve.type];
|
|
142
|
+
if (!calculator) {
|
|
143
|
+
throw new Error('INVALID_CURVE_TYPE');
|
|
144
|
+
}
|
|
145
|
+
return calculator();
|
|
146
|
+
}
|
|
147
|
+
function calcCost({ amount, decimal, currentSupply, direction, curve, }) {
|
|
148
|
+
const calculator = {
|
|
149
|
+
constant: () => calcConstantCost({ amount, decimal, ...curve }),
|
|
150
|
+
linear: () => calcLinearCost({ amount, decimal, currentSupply, direction, ...curve }),
|
|
151
|
+
quadratic: () => calcQuadraticCost({ amount, decimal, currentSupply, direction, ...curve }),
|
|
152
|
+
}[curve.type];
|
|
153
|
+
if (!calculator) {
|
|
154
|
+
throw new Error('INVALID_CURVE_TYPE');
|
|
155
|
+
}
|
|
156
|
+
return calculator();
|
|
157
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ocap/util",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "utils shared across multiple forge js libs, works in both node.js and browser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arcblock",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"bn.js": "5.2.1",
|
|
16
16
|
"bs58": "^5.0.0",
|
|
17
17
|
"lodash": "^4.17.21",
|
|
18
|
-
"utf8": "^3.0.0"
|
|
18
|
+
"utf8": "^3.0.0",
|
|
19
|
+
"@ocap/types": "^1.22.0"
|
|
19
20
|
},
|
|
20
21
|
"resolutions": {
|
|
21
22
|
"bn.js": "5.2.1",
|