@mimicprotocol/lib-ts 0.0.1-rc.9

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.
@@ -0,0 +1,248 @@
1
+ import { environment } from '../environment'
2
+ import { join, parseCSV, Serializable, serialize } from '../helpers'
3
+ import { BigInt } from '../types'
4
+
5
+ import { Token } from './Token'
6
+ import { USD } from './USD'
7
+
8
+ /**
9
+ * Represents an amount of a specific token, combining the token metadata with a quantity.
10
+ * Supports arithmetic operations, comparisons, and conversions between tokens and USD.
11
+ */
12
+ export class TokenAmount implements Serializable {
13
+ private static readonly SERIALIZED_PREFIX: string = 'TokenAmount'
14
+
15
+ private _token: Token
16
+ private _amount: BigInt
17
+
18
+ /**
19
+ * Creates a TokenAmount from a decimal string representation.
20
+ * @param token - The token to create an amount for
21
+ * @param amount - The amount as a decimal string (e.g., "1.5", "100.0")
22
+ * @returns A new TokenAmount instance
23
+ */
24
+ static fromStringDecimal(token: Token, amount: string): TokenAmount {
25
+ return this.fromBigInt(token, BigInt.fromStringDecimal(amount, token.decimals))
26
+ }
27
+
28
+ /**
29
+ * Creates a TokenAmount from a 32-bit integer.
30
+ * @param token - The token to create an amount for
31
+ * @param amount - The amount as a whole number (will be scaled by token decimals)
32
+ * @returns A new TokenAmount instance
33
+ */
34
+ static fromI32(token: Token, amount: i32): TokenAmount {
35
+ return this.fromBigInt(token, BigInt.fromI32(amount).upscale(token.decimals))
36
+ }
37
+
38
+ /**
39
+ * Creates a TokenAmount from a BigInt amount.
40
+ * @param token - The token to create an amount for
41
+ * @param amount - The amount in the token's smallest unit (e.g., wei for ETH)
42
+ * @returns A new TokenAmount instance
43
+ */
44
+ static fromBigInt(token: Token, amount: BigInt): TokenAmount {
45
+ return new TokenAmount(token, amount)
46
+ }
47
+
48
+ /**
49
+ * Parses a serialized TokenAmount string and creates a TokenAmount instance.
50
+ * @param serialized - The serialized string in format: TokenAmount(token,amount)
51
+ * @returns A new TokenAmount instance parsed from the serialized data
52
+ */
53
+ static parse(serialized: string): TokenAmount {
54
+ const isTokenAmount = serialized.startsWith(`${TokenAmount.SERIALIZED_PREFIX}(`) && serialized.endsWith(')')
55
+ if (!isTokenAmount) throw new Error('Invalid serialized token amount')
56
+
57
+ const elements = parseCSV(serialized.slice(TokenAmount.SERIALIZED_PREFIX.length + 1, -1))
58
+ const areNull = elements.some((element) => element === null)
59
+ if (areNull) throw new Error('Invalid serialized token amount')
60
+
61
+ const token = Token.parse(elements[0]!)
62
+ const amount = BigInt.parse(elements[1]!)
63
+
64
+ return new TokenAmount(token, amount)
65
+ }
66
+
67
+ /**
68
+ * Creates a new TokenAmount instance.
69
+ * @param token - The token this amount represents
70
+ * @param amount - The amount in the token's smallest unit (must be non-negative)
71
+ */
72
+ constructor(token: Token, amount: BigInt) {
73
+ if (amount.isNegative()) throw new Error('Token amount cannot be negative')
74
+ this._token = token
75
+ this._amount = amount.clone()
76
+ }
77
+
78
+ get token(): Token {
79
+ return this._token
80
+ }
81
+
82
+ get amount(): BigInt {
83
+ return this._amount.clone()
84
+ }
85
+
86
+ get symbol(): string {
87
+ return this.token.symbol
88
+ }
89
+
90
+ get decimals(): u8 {
91
+ return this.token.decimals
92
+ }
93
+
94
+ /**
95
+ * Checks if this token amount is zero.
96
+ * @returns True if the amount is zero
97
+ */
98
+ isZero(): boolean {
99
+ return this.amount.isZero()
100
+ }
101
+
102
+ /**
103
+ * Adds another TokenAmount to this one.
104
+ * @param other - The TokenAmount to add (must be the same token)
105
+ * @returns A new TokenAmount representing the sum
106
+ */
107
+ @operator('+')
108
+ plus(other: TokenAmount): TokenAmount {
109
+ this.checkToken(other.token, 'add')
110
+ return TokenAmount.fromBigInt(this.token, this.amount.plus(other.amount))
111
+ }
112
+
113
+ /**
114
+ * Subtracts another TokenAmount from this one.
115
+ * @param other - The TokenAmount to subtract (must be the same token)
116
+ * @returns A new TokenAmount representing the difference
117
+ */
118
+ @operator('-')
119
+ minus(other: TokenAmount): TokenAmount {
120
+ this.checkToken(other.token, 'subtract')
121
+ return TokenAmount.fromBigInt(this.token, this.amount.minus(other.amount))
122
+ }
123
+
124
+ /**
125
+ * Multiplies this TokenAmount by a BigInt factor.
126
+ * @param other - The BigInt to multiply by
127
+ * @returns A new TokenAmount representing the product
128
+ */
129
+ @operator('*')
130
+ times(other: BigInt): TokenAmount {
131
+ return TokenAmount.fromBigInt(this.token, this.amount.times(other))
132
+ }
133
+
134
+ /**
135
+ * Divides this TokenAmount by a BigInt divisor.
136
+ * @param other - The BigInt to divide by (cannot be zero)
137
+ * @returns A new TokenAmount representing the quotient
138
+ */
139
+ @operator('/')
140
+ div(other: BigInt): TokenAmount {
141
+ return TokenAmount.fromBigInt(this.token, this.amount.div(other))
142
+ }
143
+
144
+ /**
145
+ * Checks if this TokenAmount is less than another.
146
+ * @param other - The TokenAmount to compare with (must be the same token)
147
+ * @returns True if this amount is smaller
148
+ */
149
+ @operator('<')
150
+ lt(other: TokenAmount): boolean {
151
+ this.checkToken(other.token, 'lt')
152
+ return this.amountCompare(other) < 0
153
+ }
154
+
155
+ /**
156
+ * Checks if this TokenAmount is greater than another.
157
+ * @param other - The TokenAmount to compare with (must be the same token)
158
+ * @returns True if this amount is larger
159
+ */
160
+ @operator('>')
161
+ gt(other: TokenAmount): boolean {
162
+ this.checkToken(other.token, 'gt')
163
+ return this.amountCompare(other) > 0
164
+ }
165
+
166
+ /**
167
+ * Checks if this TokenAmount is less than or equal to another.
168
+ * @param other - The TokenAmount to compare with (must be the same token)
169
+ * @returns True if this amount is smaller or equal
170
+ */
171
+ @operator('<=')
172
+ le(other: TokenAmount): boolean {
173
+ this.checkToken(other.token, 'le')
174
+ return this.amountCompare(other) <= 0
175
+ }
176
+
177
+ /**
178
+ * Checks if this TokenAmount is greater than or equal to another.
179
+ * @param other - The TokenAmount to compare with (must be the same token)
180
+ * @returns True if this amount is larger or equal
181
+ */
182
+ @operator('>=')
183
+ ge(other: TokenAmount): boolean {
184
+ this.checkToken(other.token, 'ge')
185
+ return this.amountCompare(other) >= 0
186
+ }
187
+
188
+ /**
189
+ * Checks if this TokenAmount is equal to another.
190
+ * @param other - The TokenAmount to compare with
191
+ * @returns True if both represent the same token and amount
192
+ */
193
+ @operator('==')
194
+ equals(other: TokenAmount): boolean {
195
+ return this.token.equals(other.token) && this.amountCompare(other) === 0
196
+ }
197
+
198
+ /**
199
+ * Checks if this TokenAmount is not equal to another.
200
+ * @param other - The TokenAmount to compare with
201
+ * @returns True if they represent different tokens or amounts
202
+ */
203
+ @operator('!=')
204
+ notEquals(other: TokenAmount): boolean {
205
+ return !this.token.equals(other.token) || this.amountCompare(other) !== 0
206
+ }
207
+
208
+ /**
209
+ * Tells the string representation of this TokenAmount.
210
+ * @returns Formatted string showing the decimal amount and symbol (e.g., "1.5 ETH")
211
+ */
212
+ toString(): string {
213
+ return `${this.amount.toStringDecimal(this.decimals)} ${this.token.symbol}`
214
+ }
215
+
216
+ /**
217
+ * Converts this TokenAmount to its USD equivalent.
218
+ * @returns A USD instance representing the current USD value
219
+ */
220
+ toUsd(): USD {
221
+ if (this.isZero()) return USD.zero()
222
+ const tokenPrice = environment.getPrice(this.token)
223
+ const amountUsd = this.amount.times(tokenPrice.value).downscale(this.decimals)
224
+ return USD.fromBigInt(amountUsd)
225
+ }
226
+
227
+ /**
228
+ * Converts this TokenAmount to an equivalent amount of another token.
229
+ * @param other - The target token to convert to
230
+ * @returns A TokenAmount of the target token with equivalent USD value
231
+ */
232
+ toTokenAmount(other: Token): TokenAmount {
233
+ if (this.isZero()) return TokenAmount.fromI32(other, 0)
234
+ return this.toUsd().toTokenAmount(other)
235
+ }
236
+
237
+ serialize(): string {
238
+ return `${TokenAmount.SERIALIZED_PREFIX}(${join([serialize(this.token), serialize(this.amount)])})`
239
+ }
240
+
241
+ private amountCompare(other: TokenAmount): i32 {
242
+ return BigInt.compare(this._amount, other.amount)
243
+ }
244
+
245
+ private checkToken(other: Token, action: string): void {
246
+ if (!this.token.equals(other)) throw new Error(`Cannot ${action} different tokens`)
247
+ }
248
+ }
@@ -0,0 +1,201 @@
1
+ import { environment } from '../environment'
2
+ import { STANDARD_DECIMALS } from '../helpers'
3
+ import { Token, TokenAmount } from '../tokens'
4
+ import { BigInt } from '../types'
5
+
6
+ /**
7
+ * Represents a USD amount with fixed decimal precision.
8
+ * Supports arithmetic operations, comparisons, and conversions to token amounts.
9
+ */
10
+ export class USD {
11
+ private _value: BigInt
12
+
13
+ /**
14
+ * Creates a USD instance representing zero dollars.
15
+ * @returns A new USD instance with value 0
16
+ */
17
+ static zero(): USD {
18
+ return new USD(BigInt.zero())
19
+ }
20
+
21
+ /**
22
+ * Creates a USD instance from a decimal string representation.
23
+ * @param amount - The amount as a decimal string (e.g., "1.50", "100.00")
24
+ * @returns A new USD instance
25
+ */
26
+ static fromStringDecimal(amount: string): USD {
27
+ return USD.fromBigInt(BigInt.fromStringDecimal(amount, STANDARD_DECIMALS))
28
+ }
29
+
30
+ /**
31
+ * Creates a USD instance from a 32-bit integer.
32
+ * @param amount - The amount as a whole number (e.g., 150 for $150.00)
33
+ * @returns A new USD instance
34
+ */
35
+ static fromI32(amount: i32): USD {
36
+ return USD.fromBigInt(BigInt.fromI32(amount).upscale(STANDARD_DECIMALS))
37
+ }
38
+
39
+ /**
40
+ * Creates a USD instance from a BigInt amount.
41
+ * @param amount - The amount in 18 decimals precision (must be non-negative)
42
+ * @returns A new USD instance
43
+ */
44
+ static fromBigInt(amount: BigInt): USD {
45
+ if (amount.isNegative()) throw new Error('USD cannot be negative')
46
+ return new USD(amount)
47
+ }
48
+
49
+ /**
50
+ * Creates a new USD instance.
51
+ * @param amount - The amount in 18 decimals precision (must be non-negative)
52
+ */
53
+ constructor(amount: BigInt) {
54
+ this._value = amount.clone()
55
+ }
56
+
57
+ /**
58
+ * Tells the value of this USD amount in 18 decimals precision.
59
+ * @returns A new BigInt instance representing the value
60
+ */
61
+ get value(): BigInt {
62
+ return this._value.clone()
63
+ }
64
+
65
+ /**
66
+ * Checks if this USD amount is zero.
67
+ * @returns True if the amount is zero
68
+ */
69
+ isZero(): boolean {
70
+ return this.value.isZero()
71
+ }
72
+
73
+ /**
74
+ * Adds another USD amount to this one.
75
+ * @param other - The USD amount to add
76
+ * @returns A new USD instance representing the sum
77
+ */
78
+ @operator('+')
79
+ plus(other: USD): USD {
80
+ return USD.fromBigInt(this.value.plus(other.value))
81
+ }
82
+
83
+ /**
84
+ * Subtracts another USD amount from this one.
85
+ * @param other - The USD amount to subtract
86
+ * @returns A new USD instance representing the difference
87
+ */
88
+ @operator('-')
89
+ minus(other: USD): USD {
90
+ return USD.fromBigInt(this.value.minus(other.value))
91
+ }
92
+
93
+ /**
94
+ * Multiplies this USD amount by a BigInt factor.
95
+ * @param other - The BigInt to multiply by
96
+ * @returns A new USD instance representing the product
97
+ */
98
+ @operator('*')
99
+ times(other: BigInt): USD {
100
+ return USD.fromBigInt(this.value.times(other))
101
+ }
102
+
103
+ /**
104
+ * Divides this USD amount by a BigInt divisor.
105
+ * @param other - The BigInt to divide by (cannot be zero)
106
+ * @returns A new USD instance representing the quotient
107
+ */
108
+ @operator('/')
109
+ div(other: BigInt): USD {
110
+ return USD.fromBigInt(this.value.div(other))
111
+ }
112
+
113
+ /**
114
+ * Checks if this USD amount is equal to another.
115
+ * @param other - The USD amount to compare with
116
+ * @returns True if both amounts are equal
117
+ */
118
+ @operator('==')
119
+ equals(other: USD): boolean {
120
+ return this.compare(other) === 0
121
+ }
122
+
123
+ /**
124
+ * Checks if this USD amount is not equal to another.
125
+ * @param other - The USD amount to compare with
126
+ * @returns True if the amounts are different
127
+ */
128
+ @operator('!=')
129
+ notEquals(other: USD): boolean {
130
+ return this.compare(other) !== 0
131
+ }
132
+
133
+ /**
134
+ * Checks if this USD amount is less than another.
135
+ * @param other - The USD amount to compare with
136
+ * @returns True if this amount is smaller
137
+ */
138
+ @operator('<')
139
+ lt(other: USD): boolean {
140
+ return this.compare(other) < 0
141
+ }
142
+
143
+ /**
144
+ * Checks if this USD amount is greater than another.
145
+ * @param other - The USD amount to compare with
146
+ * @returns True if this amount is larger
147
+ */
148
+ @operator('>')
149
+ gt(other: USD): boolean {
150
+ return this.compare(other) > 0
151
+ }
152
+
153
+ /**
154
+ * Checks if this USD amount is less than or equal to another.
155
+ * @param other - The USD amount to compare with
156
+ * @returns True if this amount is smaller or equal
157
+ */
158
+ @operator('<=')
159
+ le(other: USD): boolean {
160
+ return this.compare(other) <= 0
161
+ }
162
+
163
+ /**
164
+ * Checks if this USD amount is greater than or equal to another.
165
+ * @param other - The USD amount to compare with
166
+ * @returns True if this amount is larger or equal
167
+ */
168
+ @operator('>=')
169
+ ge(other: USD): boolean {
170
+ return this.compare(other) >= 0
171
+ }
172
+
173
+ /**
174
+ * Compares this USD amount with another.
175
+ * @param other - The USD amount to compare with
176
+ * @returns -1 if smaller, 0 if equal, 1 if larger
177
+ */
178
+ compare(other: USD): i32 {
179
+ return BigInt.compare(this._value, other.value)
180
+ }
181
+
182
+ /**
183
+ * Tells the string representation of this USD amount.
184
+ * @returns Decimal string representation (e.g., "1.50", "100")
185
+ */
186
+ toString(): string {
187
+ return this._value.toStringDecimal(STANDARD_DECIMALS)
188
+ }
189
+
190
+ /**
191
+ * Converts this USD amount to an equivalent token amount.
192
+ * @param token - The target token to convert to
193
+ * @returns A TokenAmount representing the equivalent value in the target token
194
+ */
195
+ toTokenAmount(token: Token): TokenAmount {
196
+ if (this.isZero()) return TokenAmount.fromI32(token, 0)
197
+ const tokenPrice = environment.getPrice(token)
198
+ const tokenAmount = this.value.upscale(token.decimals).div(tokenPrice.value)
199
+ return TokenAmount.fromBigInt(token, tokenAmount)
200
+ }
201
+ }
@@ -0,0 +1,3 @@
1
+ export * from './Token'
2
+ export * from './TokenAmount'
3
+ export * from './USD'
@@ -0,0 +1,60 @@
1
+ // eslint-disable-next-line no-secrets/no-secrets
2
+ // This file is based on code from "The Graph Tooling" (https://github.com/graphprotocol/graph-tooling/tree/7faa3098b2e6c61f09fc81b8b2d333e66b0080d1).
3
+ // Licensed under the MIT License.
4
+ // Copyright (c) 2018 Graph Protocol, Inc. and contributors.
5
+ // Modified by Mimic Protocol, 2025.
6
+
7
+ import { ByteArray } from './ByteArray'
8
+ import { Bytes } from './Bytes'
9
+
10
+ /**
11
+ * Represents an Ethereum address, a fixed-length 20-byte value.
12
+ */
13
+ export class Address extends Bytes {
14
+ /**
15
+ * Returns a zero address (20 bytes filled with zeroes).
16
+ */
17
+ static zero(): Address {
18
+ const self = new ByteArray(20)
19
+ return changetype<Address>(self)
20
+ }
21
+
22
+ /**
23
+ * Converts a string representation of an address to an Address instance.
24
+ * It is assumed that the string is a hex string.
25
+ */
26
+ static fromString(str: string): Address {
27
+ return this.fromHexString(str)
28
+ }
29
+
30
+ /**
31
+ * Converts a hex string representation of an address to an Address instance.
32
+ */
33
+ static fromHexString(str: string): Address {
34
+ const bytes = Bytes.fromHexString(str)
35
+ return this.fromBytes(bytes)
36
+ }
37
+
38
+ /**
39
+ * Converts a Bytes instance to an Address.
40
+ * Throws an error if the input is not exactly 20 bytes long.
41
+ */
42
+ static fromBytes(bytes: Bytes): Address {
43
+ if (bytes.length != 20) throw new Error(`Bytes of length ${bytes.length} can not be converted to 20 byte addresses`)
44
+ return changetype<Address>(bytes)
45
+ }
46
+
47
+ /**
48
+ * Returns the address in hexadecimal. This method is overridden to avoid
49
+ * returning the UTF-8 encoded version of the address.
50
+ */
51
+ toString(): string {
52
+ return super.toHexString()
53
+ }
54
+
55
+ clone(): Address {
56
+ const copy = new ByteArray(this.length)
57
+ copy.set(this)
58
+ return changetype<Address>(copy)
59
+ }
60
+ }