@zofai/zo-sdk 0.1.100 → 0.2.1

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.
@@ -184,7 +184,7 @@ export class SLPDataAPI extends BaseDataAPI implements ISLPDataAPI {
184
184
  const [direction, token] = parseSymbolKey(key)
185
185
  const symbol = this.consts.sudoCore.symbols[key]
186
186
  tx.moveCall({
187
- target: `${this.consts.sudoCore.upgradedPackage}::market::valuate_symbol_v1_1`,
187
+ target: `${this.consts.sudoCore.upgradedPackage}::market::valuate_symbol_v2`,
188
188
  typeArguments: [
189
189
  `${this.consts.sudoCore.package}::slp::SLP`,
190
190
  this.consts.coins[token].module,
@@ -1209,7 +1209,24 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
1209
1209
  // OI context for funding: fetch state and paired side size when enabled
1210
1210
  const oiState = await this.getSymbolOiFundingState(positionInfo.indexToken)
1211
1211
  const pairedSymbol = await this.getSymbolInfo(positionInfo.indexToken, !positionInfo.long)
1212
- positionInfo.fundingFeeValue = ZLPDataAPI.calculatePositionFundingFee(positionInfo, await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long), (await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long)).fundingFeeModel, (await this.getOraclePrice(positionInfo.indexToken)).getPriceUnchecked().getPriceAsNumberUnchecked(), (await this.getMarketInfo()).lpSupplyWithDecimals, Date.now() / 1000, oiState && oiState.enabled ? oiState : undefined, pairedSymbol.openingSize)
1212
+ const computedFundingFeeValue = ZLPDataAPI.calculatePositionFundingFee(
1213
+ positionInfo,
1214
+ await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long),
1215
+ (await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long)).fundingFeeModel,
1216
+ (await this.getOraclePrice(positionInfo.indexToken)).getPriceUnchecked().getPriceAsNumberUnchecked(),
1217
+ (await this.getMarketInfo()).lpSupplyWithDecimals,
1218
+ Date.now() / 1000,
1219
+ oiState && oiState.enabled ? oiState : undefined,
1220
+ pairedSymbol.openingSize,
1221
+ )
1222
+ // Don't clobber a valid on-chain value with a transient 0/NaN from missing pricing/OI context.
1223
+ const existing = positionInfo.fundingFeeValue
1224
+ const computedIsFinite = Number.isFinite(computedFundingFeeValue)
1225
+ const computedIsZeroish = computedIsFinite && Math.abs(computedFundingFeeValue) < 1e-12
1226
+ const existingIsNonZeroish = Number.isFinite(existing) && Math.abs(existing) >= 1e-12
1227
+ if (computedIsFinite && !(computedIsZeroish && existingIsNonZeroish)) {
1228
+ positionInfo.fundingFeeValue = computedFundingFeeValue
1229
+ }
1213
1230
 
1214
1231
  return positionInfo
1215
1232
  }
package/src/utils.ts CHANGED
@@ -70,19 +70,72 @@ export function sDecimalToObject(sDecimal: SuiDecimal) {
70
70
 
71
71
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
72
  export function parseValue(field: any): number {
73
- if (field.type && field.type.endsWith('::decimal::Decimal')) {
74
- return decimalToObject({ value: field.fields.value })
73
+ if (field === null || field === undefined) {
74
+ return 0
75
75
  }
76
- else if (field.type && field.type.endsWith('::rate::Rate')) {
77
- return rateToObject({ value: field.fields.value })
76
+ if (typeof field === 'number') {
77
+ return field
78
78
  }
79
- else if (field.type && field.type.endsWith('::srate::SRate')) {
80
- return sRateToObject(field)
79
+ if (typeof field === 'bigint') {
80
+ return Number(field)
81
81
  }
82
- else if (field.type && field.type.endsWith('::sdecimal::SDecimal')) {
83
- return sDecimalToObject(field)
82
+ if (typeof field === 'string') {
83
+ const n = Number.parseInt(field, 10)
84
+ return Number.isFinite(n) ? n : 0
84
85
  }
85
- return Number.parseInt(field, 10)
86
+ // Some Move values arrive as nested { fields: { value: ... } } wrappers (and/or Option-like wrappers).
87
+ if (typeof field === 'object') {
88
+ // Prefer typed parsing when available.
89
+ if (field.type && field.type.endsWith('::decimal::Decimal')) {
90
+ return decimalToObject({ value: field.fields.value })
91
+ }
92
+ else if (field.type && field.type.endsWith('::rate::Rate')) {
93
+ return rateToObject({ value: field.fields.value })
94
+ }
95
+ else if (field.type && field.type.endsWith('::srate::SRate')) {
96
+ return sRateToObject(field)
97
+ }
98
+ else if (field.type && field.type.endsWith('::sdecimal::SDecimal')) {
99
+ return sDecimalToObject(field)
100
+ }
101
+
102
+ // Unwrap common wrapper patterns.
103
+ // - Option<T>: { fields: { some: T } } or { fields: { value: T } } (varies by serializer)
104
+ // - Inner wrappers: { fields: { value: <primitive or struct> } }
105
+ const unwrapKeys = ['some', 'value', 'inner']
106
+ let cur: any = field
107
+ for (let i = 0; i < 6; i += 1) {
108
+ const f = cur?.fields
109
+ if (!f || typeof f !== 'object')
110
+ break
111
+ const nextKey = unwrapKeys.find(k => f[k] !== undefined)
112
+ if (!nextKey)
113
+ break
114
+ cur = f[nextKey]
115
+ if (cur === null || cur === undefined)
116
+ return 0
117
+ if (typeof cur === 'string') {
118
+ const n = Number.parseInt(cur, 10)
119
+ return Number.isFinite(n) ? n : 0
120
+ }
121
+ if (typeof cur === 'number')
122
+ return cur
123
+ if (typeof cur === 'bigint')
124
+ return Number(cur)
125
+ // If we hit a typed struct, recurse once to apply typed parsing.
126
+ if (typeof cur === 'object' && cur.type)
127
+ return parseValue(cur)
128
+ }
129
+
130
+ const maybeStr = (field as any)?.fields?.value
131
+ if (typeof maybeStr === 'string') {
132
+ const n = Number.parseInt(maybeStr, 10)
133
+ return Number.isFinite(n) ? n : 0
134
+ }
135
+ }
136
+
137
+ const n = Number.parseInt(String(field), 10)
138
+ return Number.isFinite(n) ? n : 0
86
139
  }
87
140
 
88
141
  export type ReversedKeyValue<T extends object> = {