@wharfkit/resources 1.0.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/LICENSE +29 -0
- package/README.md +25 -0
- package/lib/eosio-resources.d.ts +191 -0
- package/lib/eosio-resources.js +552 -0
- package/lib/eosio-resources.js.map +1 -0
- package/lib/eosio-resources.m.js +532 -0
- package/lib/eosio-resources.m.js.map +1 -0
- package/lib/wharfkit-resources.d.ts +191 -0
- package/lib/wharfkit-resources.js +552 -0
- package/lib/wharfkit-resources.js.map +1 -0
- package/lib/wharfkit-resources.m.js +532 -0
- package/lib/wharfkit-resources.m.js.map +1 -0
- package/package.json +48 -0
- package/src/index.ts +87 -0
- package/src/powerup/abstract.ts +144 -0
- package/src/powerup/cpu.ts +76 -0
- package/src/powerup/net.ts +77 -0
- package/src/powerup/options.ts +9 -0
- package/src/powerup.ts +28 -0
- package/src/ram.ts +52 -0
- package/src/rex.ts +75 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {API, APIClient, APIClientOptions, FetchProvider, UInt128} from '@wharfkit/antelope'
|
|
2
|
+
import BN from 'bn.js'
|
|
3
|
+
|
|
4
|
+
import {PowerUpAPI} from './powerup'
|
|
5
|
+
import {RAMAPI} from './ram'
|
|
6
|
+
import {REXAPI} from './rex'
|
|
7
|
+
|
|
8
|
+
export * from './powerup'
|
|
9
|
+
export * from './ram'
|
|
10
|
+
export * from './rex'
|
|
11
|
+
|
|
12
|
+
interface ResourcesOptions extends APIClientOptions {
|
|
13
|
+
api?: APIClient
|
|
14
|
+
sampleAccount?: string
|
|
15
|
+
symbol?: string
|
|
16
|
+
url?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SampleUsage {
|
|
20
|
+
account: API.v1.AccountObject
|
|
21
|
+
cpu: UInt128
|
|
22
|
+
net: UInt128
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const BNPrecision = new BN(1000 * 1000)
|
|
26
|
+
|
|
27
|
+
export class Resources {
|
|
28
|
+
static __className = 'Resources'
|
|
29
|
+
|
|
30
|
+
readonly api: APIClient
|
|
31
|
+
|
|
32
|
+
// the account to use when sampling usage
|
|
33
|
+
sampleAccount = 'b1'
|
|
34
|
+
|
|
35
|
+
// token precision/symbol
|
|
36
|
+
symbol = '4,EOS'
|
|
37
|
+
|
|
38
|
+
constructor(options: ResourcesOptions) {
|
|
39
|
+
// Allow overriding of the sample account name
|
|
40
|
+
if (options.sampleAccount) {
|
|
41
|
+
this.sampleAccount = options.sampleAccount
|
|
42
|
+
}
|
|
43
|
+
// Allow overriding of the system token symbol
|
|
44
|
+
if (options.symbol) {
|
|
45
|
+
this.symbol = options.symbol
|
|
46
|
+
}
|
|
47
|
+
// Allow variations on how to specify the API configuration
|
|
48
|
+
if (options.api) {
|
|
49
|
+
this.api = options.api
|
|
50
|
+
} else if (options.url) {
|
|
51
|
+
this.api = new APIClient({provider: new FetchProvider(options.url, options)})
|
|
52
|
+
} else {
|
|
53
|
+
throw new Error('Missing url or api client')
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
v1 = {
|
|
58
|
+
powerup: new PowerUpAPI(this),
|
|
59
|
+
ram: new RAMAPI(this),
|
|
60
|
+
rex: new REXAPI(this),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async getSampledUsage(): Promise<SampleUsage> {
|
|
64
|
+
const account = await this.api.v1.chain.get_account(this.sampleAccount)
|
|
65
|
+
const us = UInt128.from(account.cpu_limit.max.value.mul(BNPrecision))
|
|
66
|
+
const byte = UInt128.from(account.net_limit.max.value.mul(BNPrecision))
|
|
67
|
+
|
|
68
|
+
const cpu_weight = UInt128.from(account.cpu_weight.value)
|
|
69
|
+
const net_weight = UInt128.from(account.net_weight.value)
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
account,
|
|
73
|
+
cpu: divCeil(us.value, cpu_weight.value),
|
|
74
|
+
net: divCeil(byte.value, net_weight.value),
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function divCeil(num: BN, den: BN): UInt128 {
|
|
80
|
+
let v: BN = num.div(den)
|
|
81
|
+
const zero = new BN(0)
|
|
82
|
+
const one = new BN(1)
|
|
83
|
+
if (num.mod(den).gt(zero)) {
|
|
84
|
+
v = v.sub(one)
|
|
85
|
+
}
|
|
86
|
+
return UInt128.from(v)
|
|
87
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Asset,
|
|
3
|
+
Float64,
|
|
4
|
+
Int64,
|
|
5
|
+
Struct,
|
|
6
|
+
TimePointSec,
|
|
7
|
+
UInt128,
|
|
8
|
+
UInt32,
|
|
9
|
+
UInt64,
|
|
10
|
+
UInt8,
|
|
11
|
+
} from '@wharfkit/antelope'
|
|
12
|
+
|
|
13
|
+
import BN from 'bn.js'
|
|
14
|
+
import {PowerUpStateOptions} from './options'
|
|
15
|
+
|
|
16
|
+
export abstract class PowerUpStateResource extends Struct {
|
|
17
|
+
@Struct.field('uint8') version!: UInt8
|
|
18
|
+
@Struct.field('int64') weight!: Int64
|
|
19
|
+
@Struct.field('int64') weight_ratio!: Int64
|
|
20
|
+
@Struct.field('int64') assumed_stake_weight!: Int64
|
|
21
|
+
@Struct.field('int64') initial_weight_ratio!: Int64
|
|
22
|
+
@Struct.field('int64') target_weight_ratio!: Int64
|
|
23
|
+
@Struct.field('time_point_sec') initial_timestamp!: TimePointSec
|
|
24
|
+
@Struct.field('time_point_sec') target_timestamp!: TimePointSec
|
|
25
|
+
@Struct.field('float64') exponent!: Float64
|
|
26
|
+
@Struct.field('uint32') decay_secs!: UInt32
|
|
27
|
+
@Struct.field('asset') min_price!: Asset
|
|
28
|
+
@Struct.field('asset') max_price!: Asset
|
|
29
|
+
@Struct.field('int64') utilization!: Int64
|
|
30
|
+
@Struct.field('int64') adjusted_utilization!: Int64
|
|
31
|
+
@Struct.field('time_point_sec') utilization_timestamp!: TimePointSec
|
|
32
|
+
|
|
33
|
+
readonly default_block_cpu_limit: UInt64 = UInt64.from(200000)
|
|
34
|
+
readonly default_block_net_limit: UInt64 = UInt64.from(1048576000)
|
|
35
|
+
|
|
36
|
+
abstract per_day(options?: PowerUpStateOptions): number
|
|
37
|
+
|
|
38
|
+
// Get the current number of allocated units (shift from REX -> PowerUp)
|
|
39
|
+
public get allocated() {
|
|
40
|
+
return 1 - Number(this.weight_ratio) / Number(this.target_weight_ratio) / 100
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Get the current percentage of reserved units
|
|
44
|
+
public get reserved() {
|
|
45
|
+
return Number(this.utilization) / Number(this.weight)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Get the symbol definition for the token
|
|
49
|
+
public get symbol() {
|
|
50
|
+
return this.min_price.symbol
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Common casting for typed values to numbers
|
|
54
|
+
cast() {
|
|
55
|
+
return {
|
|
56
|
+
adjusted_utilization: Number(this.adjusted_utilization),
|
|
57
|
+
decay_secs: Number(this.decay_secs.value),
|
|
58
|
+
exponent: Number(this.exponent),
|
|
59
|
+
utilization: Number(this.utilization),
|
|
60
|
+
utilization_timestamp: Number(this.utilization_timestamp.value),
|
|
61
|
+
weight: Number(this.weight),
|
|
62
|
+
weight_ratio: Number(this.weight_ratio),
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L358
|
|
67
|
+
utilization_increase(sample: UInt128, frac) {
|
|
68
|
+
const {weight} = this
|
|
69
|
+
const frac128 = UInt128.from(frac)
|
|
70
|
+
const utilization_increase =
|
|
71
|
+
new BN(weight.value.mul(new BN(frac128.value))) / Math.pow(10, 15)
|
|
72
|
+
return Math.ceil(utilization_increase)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L284-L298
|
|
76
|
+
price_function(utilization: number): number {
|
|
77
|
+
const {exponent, weight} = this.cast()
|
|
78
|
+
const max_price: number = this.max_price.value
|
|
79
|
+
const min_price: number = this.min_price.value
|
|
80
|
+
let price = min_price
|
|
81
|
+
const new_exponent = exponent - 1.0
|
|
82
|
+
if (new_exponent <= 0.0) {
|
|
83
|
+
return max_price
|
|
84
|
+
} else {
|
|
85
|
+
price += (max_price - min_price) * Math.pow(utilization / weight, new_exponent)
|
|
86
|
+
}
|
|
87
|
+
return price
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L274-L280
|
|
91
|
+
price_integral_delta(start_utilization: number, end_utilization: number): number {
|
|
92
|
+
const {exponent, weight} = this.cast()
|
|
93
|
+
const max_price: number = this.max_price.value
|
|
94
|
+
const min_price: number = this.min_price.value
|
|
95
|
+
const coefficient = (max_price - min_price) / exponent
|
|
96
|
+
const start_u = start_utilization / weight
|
|
97
|
+
const end_u = end_utilization / weight
|
|
98
|
+
const delta =
|
|
99
|
+
min_price * end_u -
|
|
100
|
+
min_price * start_u +
|
|
101
|
+
coefficient * Math.pow(end_u, exponent) -
|
|
102
|
+
coefficient * Math.pow(start_u, exponent)
|
|
103
|
+
return delta
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L262-L315
|
|
107
|
+
fee(utilization_increase, adjusted_utilization) {
|
|
108
|
+
const {utilization, weight} = this.cast()
|
|
109
|
+
|
|
110
|
+
let start_utilization: number = utilization
|
|
111
|
+
const end_utilization: number = start_utilization + utilization_increase
|
|
112
|
+
|
|
113
|
+
let fee = 0
|
|
114
|
+
if (start_utilization < adjusted_utilization) {
|
|
115
|
+
fee +=
|
|
116
|
+
(this.price_function(adjusted_utilization) *
|
|
117
|
+
Math.min(utilization_increase, adjusted_utilization - start_utilization)) /
|
|
118
|
+
weight
|
|
119
|
+
start_utilization = adjusted_utilization
|
|
120
|
+
}
|
|
121
|
+
if (start_utilization < end_utilization) {
|
|
122
|
+
fee += this.price_integral_delta(start_utilization, end_utilization)
|
|
123
|
+
}
|
|
124
|
+
return fee
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Mimic: https://github.com/EOSIO/eosio.contracts/blob/d7bc0a5cc8c0c2edd4dc61b0126517d0cb46fd94/contracts/eosio.system/src/powerup.cpp#L105-L117
|
|
128
|
+
determine_adjusted_utilization(options?: PowerUpStateOptions) {
|
|
129
|
+
// Casting EOSIO types to usable formats for JS calculations
|
|
130
|
+
const {decay_secs, utilization, utilization_timestamp} = this.cast()
|
|
131
|
+
let {adjusted_utilization} = this.cast()
|
|
132
|
+
// If utilization is less than adjusted, calculate real time value
|
|
133
|
+
if (utilization < adjusted_utilization) {
|
|
134
|
+
// Create now & adjust JS timestamp to match EOSIO timestamp values
|
|
135
|
+
const ts = options && options.timestamp ? options.timestamp : new Date()
|
|
136
|
+
const now = TimePointSec.from(ts).toMilliseconds() / 1000
|
|
137
|
+
const diff: number = adjusted_utilization - utilization
|
|
138
|
+
let delta: number = diff * Math.exp(-(now - utilization_timestamp) / decay_secs)
|
|
139
|
+
delta = Math.min(Math.max(delta, 0), diff) // Clamp the delta
|
|
140
|
+
adjusted_utilization = utilization + delta
|
|
141
|
+
}
|
|
142
|
+
return adjusted_utilization
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {Struct, UInt128} from '@wharfkit/antelope'
|
|
2
|
+
|
|
3
|
+
import {BNPrecision, SampleUsage} from '..'
|
|
4
|
+
import {PowerUpStateResource} from './abstract'
|
|
5
|
+
import {PowerUpStateOptions} from './options'
|
|
6
|
+
|
|
7
|
+
@Struct.type('powerupstateresourcecpu')
|
|
8
|
+
export class PowerUpStateResourceCPU extends PowerUpStateResource {
|
|
9
|
+
// Return smallest units per day, μs (microseconds)
|
|
10
|
+
per_day = (options?: PowerUpStateOptions) => this.us_per_day(options)
|
|
11
|
+
|
|
12
|
+
// Return ms (milliseconds) per day
|
|
13
|
+
ms_per_day(options?: PowerUpStateOptions) {
|
|
14
|
+
return this.us_per_day(options) / 1000
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Return μs (microseconds) per day
|
|
18
|
+
us_per_day(options?: PowerUpStateOptions) {
|
|
19
|
+
const limit =
|
|
20
|
+
options && options.virtual_block_cpu_limit
|
|
21
|
+
? options.virtual_block_cpu_limit
|
|
22
|
+
: this.default_block_cpu_limit
|
|
23
|
+
return Number(limit) * 2 * 60 * 60 * 24
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Convert weight to μs (microseconds)
|
|
27
|
+
weight_to_us(sample: UInt128, weight: number): number {
|
|
28
|
+
return Math.ceil((weight * Number(sample)) / BNPrecision)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Convert μs (microseconds) to weight
|
|
32
|
+
us_to_weight(sample: UInt128, us: number): number {
|
|
33
|
+
return Math.floor((us / Number(sample)) * BNPrecision)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Default frac generation by smallest unit type
|
|
37
|
+
frac = (usage: SampleUsage, us: number) => this.frac_by_us(usage, us)
|
|
38
|
+
|
|
39
|
+
// Frac generation by ms (milliseconds)
|
|
40
|
+
frac_by_ms = (usage: SampleUsage, ms: number) => this.frac_by_us(usage, ms * 1000)
|
|
41
|
+
|
|
42
|
+
// Frac generation by μs (microseconds)
|
|
43
|
+
frac_by_us(usage: SampleUsage, us: number) {
|
|
44
|
+
const {weight} = this.cast()
|
|
45
|
+
const frac = this.us_to_weight(usage.cpu, us) / weight
|
|
46
|
+
return Math.floor(frac * Math.pow(10, 15))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Price generation by smallest units, μs (microseconds)
|
|
50
|
+
price_per = (usage: SampleUsage, us = 1000, options?: PowerUpStateOptions): number =>
|
|
51
|
+
this.price_per_us(usage, us, options)
|
|
52
|
+
|
|
53
|
+
// Price generation by ms (milliseconds)
|
|
54
|
+
price_per_ms = (usage: SampleUsage, ms = 1, options?: PowerUpStateOptions): number =>
|
|
55
|
+
this.price_per_us(usage, ms * 1000, options)
|
|
56
|
+
|
|
57
|
+
// Price generation by μs (microseconds)
|
|
58
|
+
price_per_us(usage: SampleUsage, us = 1000, options?: PowerUpStateOptions): number {
|
|
59
|
+
// Determine the utilization increase by this action
|
|
60
|
+
const frac = UInt128.from(this.frac(usage, us))
|
|
61
|
+
const utilization_increase = this.utilization_increase(usage.cpu, frac)
|
|
62
|
+
|
|
63
|
+
// Determine the adjusted utilization if needed
|
|
64
|
+
const adjusted_utilization = this.determine_adjusted_utilization(options)
|
|
65
|
+
|
|
66
|
+
// Derive the fee from the increase and utilization
|
|
67
|
+
const fee = this.fee(utilization_increase, adjusted_utilization)
|
|
68
|
+
|
|
69
|
+
// Force the fee up to the next highest value of precision
|
|
70
|
+
const precision = Math.pow(10, 4)
|
|
71
|
+
const value = Math.ceil(fee * precision) / precision
|
|
72
|
+
|
|
73
|
+
// Return the modified fee
|
|
74
|
+
return value
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {Struct, UInt128} from '@wharfkit/antelope'
|
|
2
|
+
|
|
3
|
+
import {BNPrecision, SampleUsage} from '..'
|
|
4
|
+
import {PowerUpStateResource} from './abstract'
|
|
5
|
+
import {PowerUpStateOptions} from './options'
|
|
6
|
+
|
|
7
|
+
@Struct.type('powerupstateresourcenet')
|
|
8
|
+
export class PowerUpStateResourceNET extends PowerUpStateResource {
|
|
9
|
+
// Return smallest units per day, bytes
|
|
10
|
+
per_day = (options?: PowerUpStateOptions) => this.bytes_per_day(options)
|
|
11
|
+
|
|
12
|
+
// Return kb per day
|
|
13
|
+
kb_per_day(options?: PowerUpStateOptions) {
|
|
14
|
+
return this.bytes_per_day(options) / 1000
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Return bytes per day
|
|
18
|
+
bytes_per_day(options?: PowerUpStateOptions) {
|
|
19
|
+
const limit =
|
|
20
|
+
options && options.virtual_block_net_limit
|
|
21
|
+
? options.virtual_block_net_limit
|
|
22
|
+
: this.default_block_net_limit
|
|
23
|
+
return Number(limit) * 2 * 60 * 60 * 24
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Convert weight to bytes
|
|
27
|
+
weight_to_bytes(sample: UInt128, weight: number): number {
|
|
28
|
+
return Math.ceil((weight * Number(sample)) / BNPrecision)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Convert bytes to weight
|
|
32
|
+
bytes_to_weight(sample: UInt128, bytes: number): number {
|
|
33
|
+
return Math.floor((bytes / Number(sample)) * BNPrecision)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Default frac generation by smallest unit type
|
|
37
|
+
frac = (usage: SampleUsage, bytes: number) => this.frac_by_bytes(usage, bytes)
|
|
38
|
+
|
|
39
|
+
// Frac generation by kb
|
|
40
|
+
frac_by_kb = (usage: SampleUsage, kilobytes: number) =>
|
|
41
|
+
this.frac_by_bytes(usage, kilobytes * 1000)
|
|
42
|
+
|
|
43
|
+
// Frac generation by bytes
|
|
44
|
+
frac_by_bytes(usage: SampleUsage, bytes: number) {
|
|
45
|
+
const {weight} = this.cast()
|
|
46
|
+
const frac = this.bytes_to_weight(usage.net, bytes) / weight
|
|
47
|
+
return Math.floor(frac * Math.pow(10, 15))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Price generation by smallest units, bytes
|
|
51
|
+
price_per = (usage: SampleUsage, bytes = 1000, options?: PowerUpStateOptions) =>
|
|
52
|
+
this.price_per_byte(usage, bytes, options)
|
|
53
|
+
|
|
54
|
+
// Price generation by kb
|
|
55
|
+
price_per_kb = (usage: SampleUsage, kilobytes = 1, options?: PowerUpStateOptions): number =>
|
|
56
|
+
this.price_per_byte(usage, kilobytes * 1000, options)
|
|
57
|
+
|
|
58
|
+
// Price generation by bytes
|
|
59
|
+
price_per_byte(usage: SampleUsage, bytes = 1000, options?: PowerUpStateOptions): number {
|
|
60
|
+
// Determine the utilization increase by this action
|
|
61
|
+
const frac = UInt128.from(this.frac(usage, bytes))
|
|
62
|
+
const utilization_increase = this.utilization_increase(usage.net, frac)
|
|
63
|
+
|
|
64
|
+
// Determine the adjusted utilization if needed
|
|
65
|
+
const adjusted_utilization = this.determine_adjusted_utilization(options)
|
|
66
|
+
|
|
67
|
+
// Derive the fee from the increase and utilization
|
|
68
|
+
const fee = this.fee(utilization_increase, adjusted_utilization)
|
|
69
|
+
|
|
70
|
+
// Force the fee up to the next highest value of precision
|
|
71
|
+
const precision = Math.pow(10, 4)
|
|
72
|
+
const value = Math.ceil(fee * precision) / precision
|
|
73
|
+
|
|
74
|
+
// Return the modified fee
|
|
75
|
+
return value
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {TimePointType, UInt64} from '@wharfkit/antelope'
|
|
2
|
+
|
|
3
|
+
export interface PowerUpStateOptions {
|
|
4
|
+
// timestamp to base adjusted_utilization off
|
|
5
|
+
timestamp?: TimePointType
|
|
6
|
+
// blockchain resource limits for calculating usage
|
|
7
|
+
virtual_block_cpu_limit?: UInt64
|
|
8
|
+
virtual_block_net_limit?: UInt64
|
|
9
|
+
}
|
package/src/powerup.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {Asset, Struct, UInt32, UInt8} from '@wharfkit/antelope'
|
|
2
|
+
|
|
3
|
+
import {Resources} from '.'
|
|
4
|
+
import {PowerUpStateResourceCPU} from './powerup/cpu'
|
|
5
|
+
import {PowerUpStateResourceNET} from './powerup/net'
|
|
6
|
+
|
|
7
|
+
@Struct.type('powerupstate')
|
|
8
|
+
export class PowerUpState extends Struct {
|
|
9
|
+
@Struct.field('uint8') version!: UInt8
|
|
10
|
+
@Struct.field(PowerUpStateResourceNET) net!: PowerUpStateResourceNET
|
|
11
|
+
@Struct.field(PowerUpStateResourceCPU) cpu!: PowerUpStateResourceCPU
|
|
12
|
+
@Struct.field('uint32') powerup_days!: UInt32
|
|
13
|
+
@Struct.field('asset') min_powerup_fee!: Asset
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class PowerUpAPI {
|
|
17
|
+
constructor(private parent: Resources) {}
|
|
18
|
+
|
|
19
|
+
async get_state(): Promise<PowerUpState> {
|
|
20
|
+
const response = await this.parent.api.v1.chain.get_table_rows({
|
|
21
|
+
code: 'eosio',
|
|
22
|
+
scope: '',
|
|
23
|
+
table: 'powup.state',
|
|
24
|
+
type: PowerUpState,
|
|
25
|
+
})
|
|
26
|
+
return response.rows[0]
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/ram.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {Resources} from './'
|
|
2
|
+
|
|
3
|
+
import {Asset, Float64, Struct} from '@wharfkit/antelope'
|
|
4
|
+
|
|
5
|
+
@Struct.type('connector')
|
|
6
|
+
export class Connector extends Struct {
|
|
7
|
+
@Struct.field('asset') balance!: Asset
|
|
8
|
+
@Struct.field('float64') weight!: Float64
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Struct.type('exchange_state')
|
|
12
|
+
export class ExchangeState extends Struct {
|
|
13
|
+
@Struct.field('asset') supply!: Asset
|
|
14
|
+
@Struct.field(Connector) base!: Connector
|
|
15
|
+
@Struct.field(Connector) quote!: Connector
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Struct.type('ramstate')
|
|
19
|
+
export class RAMState extends ExchangeState {
|
|
20
|
+
public price_per(bytes: number): number {
|
|
21
|
+
const base = this.base.balance.units.toNumber()
|
|
22
|
+
const quote = this.quote.balance.value
|
|
23
|
+
return this.get_input(base, quote, bytes)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public price_per_kb(kilobytes: number): number {
|
|
27
|
+
return this.price_per(kilobytes * 1000)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Derived from https://github.com/EOSIO/eosio.contracts/blob/f6578c45c83ec60826e6a1eeb9ee71de85abe976/contracts/eosio.system/src/exchange_state.cpp#L96
|
|
31
|
+
public get_input(base: number, quote: number, value: number): number {
|
|
32
|
+
const result = (quote * value) / (base - value)
|
|
33
|
+
if (result < 0) {
|
|
34
|
+
return 0
|
|
35
|
+
}
|
|
36
|
+
return result
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class RAMAPI {
|
|
41
|
+
constructor(private parent: Resources) {}
|
|
42
|
+
|
|
43
|
+
async get_state() {
|
|
44
|
+
const response = await this.parent.api.v1.chain.get_table_rows({
|
|
45
|
+
code: 'eosio',
|
|
46
|
+
scope: 'eosio',
|
|
47
|
+
table: 'rammarket',
|
|
48
|
+
type: RAMState,
|
|
49
|
+
})
|
|
50
|
+
return response.rows[0]
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/rex.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {BNPrecision, Resources, SampleUsage} from './'
|
|
2
|
+
|
|
3
|
+
import {Asset, Struct, UInt64, UInt8} from '@wharfkit/antelope'
|
|
4
|
+
|
|
5
|
+
@Struct.type('rexstate')
|
|
6
|
+
export class REXState extends Struct {
|
|
7
|
+
@Struct.field('uint8') version!: UInt8
|
|
8
|
+
@Struct.field('asset') total_lent!: Asset
|
|
9
|
+
@Struct.field('asset') total_unlent!: Asset
|
|
10
|
+
@Struct.field('asset') total_rent!: Asset
|
|
11
|
+
@Struct.field('asset') total_lendable!: Asset
|
|
12
|
+
@Struct.field('asset') total_rex!: Asset
|
|
13
|
+
@Struct.field('asset') namebid_proceeds!: Asset
|
|
14
|
+
@Struct.field('uint64') loan_num!: UInt64
|
|
15
|
+
|
|
16
|
+
public get reserved() {
|
|
17
|
+
return Number(this.total_lent.units) / Number(this.total_lendable.units)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public get symbol() {
|
|
21
|
+
return this.total_lent.symbol
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public get precision() {
|
|
25
|
+
return this.total_lent.symbol.precision
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public get value() {
|
|
29
|
+
return (
|
|
30
|
+
(Number(this.total_lent.units) + Number(this.total_unlent.units)) /
|
|
31
|
+
Number(this.total_rex.units)
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exchange(amount: Asset): Asset {
|
|
36
|
+
return Asset.from(
|
|
37
|
+
(amount.value * this.total_lendable.value) / this.total_rex.value,
|
|
38
|
+
this.symbol
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
price_per(sample: SampleUsage, unit = 1000): number {
|
|
43
|
+
// Sample token units
|
|
44
|
+
const tokens = Asset.fromUnits(10000, this.symbol)
|
|
45
|
+
|
|
46
|
+
// Spending 1 EOS (10000 units) on REX gives this many tokens
|
|
47
|
+
const bancor = Number(tokens.units) / (this.total_rent.value / this.total_unlent.value)
|
|
48
|
+
|
|
49
|
+
// The ratio of the number of tokens received vs the sampled values
|
|
50
|
+
const unitPrice = bancor * (Number(sample.cpu) / BNPrecision)
|
|
51
|
+
|
|
52
|
+
// The token units spent per unit
|
|
53
|
+
const perunit = Number(tokens.units) / unitPrice
|
|
54
|
+
|
|
55
|
+
// Multiply the per unit cost by the units requested
|
|
56
|
+
const cost = perunit * unit
|
|
57
|
+
|
|
58
|
+
// Converting to an Asset
|
|
59
|
+
return cost / Math.pow(10, this.precision)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class REXAPI {
|
|
64
|
+
constructor(private parent: Resources) {}
|
|
65
|
+
|
|
66
|
+
async get_state() {
|
|
67
|
+
const response = await this.parent.api.v1.chain.get_table_rows({
|
|
68
|
+
code: 'eosio',
|
|
69
|
+
scope: 'eosio',
|
|
70
|
+
table: 'rexpool',
|
|
71
|
+
type: REXState,
|
|
72
|
+
})
|
|
73
|
+
return response.rows[0]
|
|
74
|
+
}
|
|
75
|
+
}
|