@zofai/zo-sdk 0.2.14 → 0.2.15

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.
Files changed (108) hide show
  1. package/dist/abstract/BaseDataAPI.cjs +1 -1
  2. package/dist/abstract/BaseDataAPI.cjs.map +1 -1
  3. package/dist/abstract/BaseDataAPI.mjs +1 -1
  4. package/dist/abstract/BaseDataAPI.mjs.map +1 -1
  5. package/dist/consts/deployments-usdz-mainnet.json +1 -1
  6. package/dist/consts/deployments-zo-oracle-mainnet.json +329 -0
  7. package/dist/consts/index.cjs +35 -1
  8. package/dist/consts/index.cjs.map +1 -1
  9. package/dist/consts/index.d.cts +45 -0
  10. package/dist/consts/index.d.cts.map +1 -1
  11. package/dist/consts/index.d.mts +45 -0
  12. package/dist/consts/index.d.mts.map +1 -1
  13. package/dist/consts/index.mjs +31 -0
  14. package/dist/consts/index.mjs.map +1 -1
  15. package/dist/data.cjs +1 -1
  16. package/dist/data.cjs.map +1 -1
  17. package/dist/data.mjs +1 -1
  18. package/dist/data.mjs.map +1 -1
  19. package/dist/implementations/USDZAPI.cjs +426 -78
  20. package/dist/implementations/USDZAPI.cjs.map +1 -1
  21. package/dist/implementations/USDZAPI.d.cts +54 -0
  22. package/dist/implementations/USDZAPI.d.cts.map +1 -1
  23. package/dist/implementations/USDZAPI.d.mts +54 -0
  24. package/dist/implementations/USDZAPI.d.mts.map +1 -1
  25. package/dist/implementations/USDZAPI.mjs +427 -79
  26. package/dist/implementations/USDZAPI.mjs.map +1 -1
  27. package/dist/implementations/USDZDataAPI.cjs +38 -0
  28. package/dist/implementations/USDZDataAPI.cjs.map +1 -1
  29. package/dist/implementations/USDZDataAPI.d.cts +16 -0
  30. package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
  31. package/dist/implementations/USDZDataAPI.d.mts +16 -0
  32. package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
  33. package/dist/implementations/USDZDataAPI.mjs +38 -0
  34. package/dist/implementations/USDZDataAPI.mjs.map +1 -1
  35. package/dist/index.cjs +3 -0
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +3 -0
  38. package/dist/index.d.cts.map +1 -1
  39. package/dist/index.d.mts +3 -0
  40. package/dist/index.d.mts.map +1 -1
  41. package/dist/index.mjs +3 -0
  42. package/dist/index.mjs.map +1 -1
  43. package/dist/interfaces/base.d.cts +19 -1
  44. package/dist/interfaces/base.d.cts.map +1 -1
  45. package/dist/interfaces/base.d.mts +19 -1
  46. package/dist/interfaces/base.d.mts.map +1 -1
  47. package/dist/interfaces/usdz.d.cts +17 -0
  48. package/dist/interfaces/usdz.d.cts.map +1 -1
  49. package/dist/interfaces/usdz.d.mts +17 -0
  50. package/dist/interfaces/usdz.d.mts.map +1 -1
  51. package/dist/oracle.cjs +119 -1
  52. package/dist/oracle.cjs.map +1 -1
  53. package/dist/oracle.d.cts +57 -1
  54. package/dist/oracle.d.cts.map +1 -1
  55. package/dist/oracle.d.mts +57 -1
  56. package/dist/oracle.d.mts.map +1 -1
  57. package/dist/oracle.mjs +120 -2
  58. package/dist/oracle.mjs.map +1 -1
  59. package/dist/oraclePro.cjs +214 -0
  60. package/dist/oraclePro.cjs.map +1 -0
  61. package/dist/oraclePro.d.cts +92 -0
  62. package/dist/oraclePro.d.cts.map +1 -0
  63. package/dist/oraclePro.d.mts +92 -0
  64. package/dist/oraclePro.d.mts.map +1 -0
  65. package/dist/oraclePro.mjs +196 -0
  66. package/dist/oraclePro.mjs.map +1 -0
  67. package/dist/pythProClient.cjs +277 -0
  68. package/dist/pythProClient.cjs.map +1 -0
  69. package/dist/pythProClient.d.cts +143 -0
  70. package/dist/pythProClient.d.cts.map +1 -0
  71. package/dist/pythProClient.d.mts +143 -0
  72. package/dist/pythProClient.d.mts.map +1 -0
  73. package/dist/pythProClient.mjs +269 -0
  74. package/dist/pythProClient.mjs.map +1 -0
  75. package/dist/storkClient.cjs +217 -0
  76. package/dist/storkClient.cjs.map +1 -0
  77. package/dist/storkClient.d.cts +90 -0
  78. package/dist/storkClient.d.cts.map +1 -0
  79. package/dist/storkClient.d.mts +90 -0
  80. package/dist/storkClient.d.mts.map +1 -0
  81. package/dist/storkClient.mjs +208 -0
  82. package/dist/storkClient.mjs.map +1 -0
  83. package/dist/storkOracle.cjs +61 -0
  84. package/dist/storkOracle.cjs.map +1 -0
  85. package/dist/storkOracle.d.cts +21 -0
  86. package/dist/storkOracle.d.cts.map +1 -0
  87. package/dist/storkOracle.d.mts +21 -0
  88. package/dist/storkOracle.d.mts.map +1 -0
  89. package/dist/storkOracle.mjs +56 -0
  90. package/dist/storkOracle.mjs.map +1 -0
  91. package/package.json +1 -1
  92. package/src/abstract/BaseDataAPI.ts +1 -1
  93. package/src/consts/deployments-usdz-mainnet.json +1 -1
  94. package/src/consts/deployments-zo-oracle-mainnet.json +329 -0
  95. package/src/consts/index.ts +80 -0
  96. package/src/data.ts +1 -1
  97. package/src/implementations/USDZAPI.ts +731 -101
  98. package/src/implementations/USDZDataAPI.ts +42 -0
  99. package/src/index.ts +3 -0
  100. package/src/interfaces/base.ts +54 -1
  101. package/src/interfaces/usdz.ts +125 -0
  102. package/src/oracle.ts +222 -1
  103. package/src/oraclePro.ts +312 -0
  104. package/src/pythProClient.ts +406 -0
  105. package/src/storkClient.ts +328 -0
  106. package/src/storkOracle.ts +82 -0
  107. package/tests/pythProClient.test.ts +155 -0
  108. package/tests/storkClient.test.ts +316 -0
@@ -0,0 +1,316 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+
3
+ import {
4
+ buildStorkUpdateDataFromSignedPrice,
5
+ fetchStorkUpdateDataFromKronos,
6
+ getLatestStorkPrices,
7
+ hexToBytes,
8
+ parseStorkUpdateDataRaw,
9
+ } from '../src/storkClient'
10
+ import { appendStorkUpdatesToTransaction, estimateStorkUpdateFeeMist } from '../src/storkOracle'
11
+ import { Transaction } from '@mysten/sui/transactions'
12
+
13
+ const SAMPLE_ID = `0x${'ab'.repeat(32)}`
14
+
15
+ describe('storkClient', () => {
16
+ it('parses kronos update_data payload', () => {
17
+ const update = parseStorkUpdateDataRaw({
18
+ id: SAMPLE_ID,
19
+ temporal_numeric_value_timestamp_ns: 123,
20
+ temporal_numeric_value_magnitude: '1000000000000000000',
21
+ temporal_numeric_value_negative: false,
22
+ publisher_merkle_root: '0x01',
23
+ value_compute_alg_hash: '0x02',
24
+ r: '0x03',
25
+ s: '0x04',
26
+ v: 27,
27
+ })
28
+ expect(update.id.length).toBe(32)
29
+ expect(update.temporalNumericValueMagnitude).toBe(10n ** 18n)
30
+ expect(update.v).toBe(27)
31
+ })
32
+
33
+ it('getLatestStorkPrices calls kronos REST', async () => {
34
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
35
+ ok: true,
36
+ json: async () => ({
37
+ success: true,
38
+ data: {
39
+ prices: {
40
+ BTCUSD: {
41
+ asset_id: 'BTCUSD',
42
+ price: '100000000000000000000',
43
+ update_data: {
44
+ id: SAMPLE_ID,
45
+ temporal_numeric_value_timestamp_ns: 1,
46
+ temporal_numeric_value_magnitude: '1',
47
+ temporal_numeric_value_negative: false,
48
+ publisher_merkle_root: '0x01',
49
+ value_compute_alg_hash: '0x02',
50
+ r: '0x03',
51
+ s: '0x04',
52
+ v: 27,
53
+ },
54
+ },
55
+ },
56
+ },
57
+ }),
58
+ }))
59
+
60
+ const data = await getLatestStorkPrices('http://localhost:8080', { assets: ['BTCUSD'] })
61
+ expect(data.prices.BTCUSD.asset_id).toBe('BTCUSD')
62
+ })
63
+
64
+ it('fetchStorkUpdateDataFromKronos returns parsed updates', async () => {
65
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
66
+ ok: true,
67
+ json: async () => ({
68
+ success: true,
69
+ data: {
70
+ prices: {
71
+ BTCUSD: {
72
+ asset_id: 'BTCUSD',
73
+ price: '1',
74
+ update_data: {
75
+ id: SAMPLE_ID,
76
+ temporal_numeric_value_timestamp_ns: 1,
77
+ temporal_numeric_value_magnitude: '1',
78
+ temporal_numeric_value_negative: false,
79
+ publisher_merkle_root: '0x01',
80
+ value_compute_alg_hash: '0x02',
81
+ r: '0x03',
82
+ s: '0x04',
83
+ v: 27,
84
+ },
85
+ },
86
+ },
87
+ },
88
+ }),
89
+ }))
90
+
91
+ const updates = await fetchStorkUpdateDataFromKronos('http://localhost:8080', ['BTCUSD'])
92
+ expect(updates).toHaveLength(1)
93
+ })
94
+
95
+ it('accepts string timestamp from stork_signed_price (no float64 truncation)', () => {
96
+ const entry = {
97
+ asset_id: 'BTCUSD',
98
+ price: '64319215652687504000000',
99
+ stork_signed_price: {
100
+ encoded_asset_id: '0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de',
101
+ price: '64319215652687504000000',
102
+ publisher_merkle_root: '0xcbe0ea2a350df5e5a386587ecf1764ada3e744b67564f0146e12f25bd8b4aebd',
103
+ calculation_alg: {
104
+ checksum: '9be7e9f9ed459417d96112a7467bd0b27575a2c7847195c68f805b70ce1795ba',
105
+ },
106
+ timestamped_signature: {
107
+ // String preserves exact u64 — the correct on-chain value
108
+ timestamp: '1782014930584673519',
109
+ signature: {
110
+ r: '0x668ea843c69fe1eb8dd1d0c8275b3acac2eea7fe9947b2dbac2aceb288195359',
111
+ s: '0x3c3d2236f2b175e26d5191185eac31b6a95ce99bad6cd1bdee1586cef40b3766',
112
+ v: '0x1b',
113
+ },
114
+ },
115
+ },
116
+ }
117
+
118
+ const update = buildStorkUpdateDataFromSignedPrice(entry)
119
+ expect(update?.temporalNumericValueTimestampNs).toBe(1782014930584673519n)
120
+ expect(update?.temporalNumericValueMagnitude).toBe(64319215652687504000000n)
121
+ expect(update?.v).toBe(27)
122
+ })
123
+
124
+ it('falls back to update_data string timestamp when stork_signed_price timestamp is a number', () => {
125
+ // Kronos returns stork_signed_price.timestamp as a JSON number (float64 truncated)
126
+ // and update_data.temporal_numeric_value_timestamp_ns as a string (exact u64).
127
+ // The SDK must use the string from update_data to avoid EInvalidSignature on-chain.
128
+ const truncatedNumberTs = 1782148271583801600 // float64 of real ts 1782148271583801715
129
+ const exactStringTs = '1782148271583801715'
130
+
131
+ const entry = {
132
+ asset_id: 'BTCUSD',
133
+ price: '64594662603625009000000',
134
+ update_data: {
135
+ id: '0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de',
136
+ temporal_numeric_value_timestamp_ns: exactStringTs,
137
+ temporal_numeric_value_magnitude: '64594662603625009000000',
138
+ temporal_numeric_value_negative: false,
139
+ publisher_merkle_root: '0xd3bbe3d69002f7db6e14da284506c5071539bd47ce4134fa48fc805a2c40f29e',
140
+ value_compute_alg_hash: '9be7e9f9ed459417d96112a7467bd0b27575a2c7847195c68f805b70ce1795ba',
141
+ r: '0x5e2a8d7c1a62842924a7abda81c65024544a65f3447d77dd1686d150bc7527a0',
142
+ s: '0x0bf5d68c5705335ab40ba63f31d03b54547376f7bb3ec6551a91dc03e39d7b7b',
143
+ v: 27,
144
+ },
145
+ stork_signed_price: {
146
+ public_key: '0x0a803F9b1CCe32e2773e0d2e98b37E0775cA5d44',
147
+ encoded_asset_id: '0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de',
148
+ price: '64594662603625009000000',
149
+ publisher_merkle_root: '0xd3bbe3d69002f7db6e14da284506c5071539bd47ce4134fa48fc805a2c40f29e',
150
+ calculation_alg: {
151
+ checksum: '9be7e9f9ed459417d96112a7467bd0b27575a2c7847195c68f805b70ce1795ba',
152
+ },
153
+ timestamped_signature: {
154
+ timestamp: truncatedNumberTs, // float64-truncated — wrong for on-chain use
155
+ msg_hash: '0x57b69c9ea90ee0492d4ab0149c817b16d95645121837bf031cb0cec3a8ba7d83',
156
+ signature: {
157
+ r: '0x5e2a8d7c1a62842924a7abda81c65024544a65f3447d77dd1686d150bc7527a0',
158
+ s: '0x0bf5d68c5705335ab40ba63f31d03b54547376f7bb3ec6551a91dc03e39d7b7b',
159
+ v: '0x1b',
160
+ },
161
+ },
162
+ },
163
+ }
164
+
165
+ const update = buildStorkUpdateDataFromSignedPrice(entry)
166
+ // Must use the exact string timestamp, not the float64-truncated number
167
+ expect(update?.temporalNumericValueTimestampNs).toBe(1782148271583801715n)
168
+ expect(update?.temporalNumericValueTimestampNs).not.toBe(BigInt(truncatedNumberTs))
169
+ })
170
+
171
+ it('uses stork_signed_price over update_data', () => {
172
+ const update = buildStorkUpdateDataFromSignedPrice({
173
+ asset_id: 'BTCUSD',
174
+ price: '999',
175
+ update_data: {
176
+ id: SAMPLE_ID,
177
+ temporal_numeric_value_timestamp_ns: 1,
178
+ temporal_numeric_value_magnitude: '1',
179
+ temporal_numeric_value_negative: false,
180
+ publisher_merkle_root: '0x01',
181
+ value_compute_alg_hash: '0x02',
182
+ r: '0x03',
183
+ s: '0x04',
184
+ v: 27,
185
+ },
186
+ stork_signed_price: {
187
+ encoded_asset_id: '0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de',
188
+ price: '64340643513099996000000',
189
+ publisher_merkle_root: '0xce95788915171eab496e1f6318b4f94065ca94d49b121627deaa5087e433fd8b',
190
+ calculation_alg: {
191
+ checksum: '9be7e9f9ed459417d96112a7467bd0b27575a2c7847195c68f805b70ce1795ba',
192
+ },
193
+ timestamped_signature: {
194
+ timestamp: '1782012523783284700',
195
+ signature: {
196
+ r: '0x6abb61d61751c5f533833260bcf15f076498ef0fabdfdd9ce73ff4bf55f1e8a6',
197
+ s: '0x6a1747bc57e098950c683457e0e8e20707b71be704a648eca16477f82ad29151',
198
+ v: '0x1b',
199
+ },
200
+ },
201
+ },
202
+ })
203
+
204
+ expect(update?.temporalNumericValueTimestampNs).toBe(1782012523783284700n)
205
+ expect(update?.temporalNumericValueMagnitude).toBe(64340643513099996000000n)
206
+ })
207
+
208
+ it('buildStorkUpdateDataFromSignedPrice matches Go ToUpdateData conversion', () => {
209
+ const update = buildStorkUpdateDataFromSignedPrice({
210
+ asset_id: 'BTCUSD',
211
+ price: '64340643513099996000000',
212
+ stork_signed_price: {
213
+ public_key: '0x0a803F9b1CCe32e2773e0d2e98b37E0775cA5d44',
214
+ encoded_asset_id: '0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de',
215
+ price: '64340643513099996000000',
216
+ timestamped_signature: {
217
+ signature: {
218
+ r: '0x6abb61d61751c5f533833260bcf15f076498ef0fabdfdd9ce73ff4bf55f1e8a6',
219
+ s: '0x6a1747bc57e098950c683457e0e8e20707b71be704a648eca16477f82ad29151',
220
+ v: '0x1b',
221
+ },
222
+ timestamp: '1782012523783284700',
223
+ msg_hash: '0x88e8f9e4d5036ef248b2c1a7fae0b00c39095b2bab955bb1149332b4d90c821d',
224
+ },
225
+ publisher_merkle_root: '0xce95788915171eab496e1f6318b4f94065ca94d49b121627deaa5087e433fd8b',
226
+ calculation_alg: {
227
+ type: 'median',
228
+ version: 'v1',
229
+ checksum: '9be7e9f9ed459417d96112a7467bd0b27575a2c7847195c68f805b70ce1795ba',
230
+ },
231
+ },
232
+ })
233
+
234
+ expect(update?.id).toEqual(hexToBytes('0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de'))
235
+ expect(update?.id.length).toBe(32)
236
+ expect(update?.temporalNumericValueTimestampNs).toBe(1782012523783284700n)
237
+ expect(update?.temporalNumericValueMagnitude).toBe(64340643513099996000000n)
238
+ expect(update?.temporalNumericValueNegative).toBe(false)
239
+ expect(update?.valueComputeAlgHash).toEqual(hexToBytes('9be7e9f9ed459417d96112a7467bd0b27575a2c7847195c68f805b70ce1795ba'))
240
+ expect(update?.v).toBe(27)
241
+ })
242
+
243
+ it('buildStorkUpdateDataFromSignedPrice uses feederId when encoded_asset_id absent', () => {
244
+ const feederId = hexToBytes(`0x${'74'.repeat(32)}`)
245
+
246
+ const update = buildStorkUpdateDataFromSignedPrice(
247
+ {
248
+ asset_id: 'BTCUSD',
249
+ price: '1000000000000000000',
250
+ stork_signed_price: {
251
+ price: '1000000000000000000',
252
+ publisher_merkle_root: '0x0101',
253
+ calculation_alg: { checksum: '0x0202' },
254
+ timestamped_signature: {
255
+ timestamp: 999,
256
+ signature: { r: '0x0303', s: '0x0404', v: '27' },
257
+ },
258
+ },
259
+ },
260
+ feederId,
261
+ )
262
+
263
+ expect(update?.id).toEqual(feederId)
264
+ expect(update?.id.length).toBe(32)
265
+ })
266
+
267
+ it('buildStorkUpdateDataFromSignedPrice decodes hex encoded_asset_id', () => {
268
+ const update = buildStorkUpdateDataFromSignedPrice({
269
+ asset_id: 'BTCUSD',
270
+ price: '1000000000000000000',
271
+ stork_signed_price: {
272
+ encoded_asset_id: `0x${'07'.repeat(32)}`,
273
+ price: '1000000000000000000',
274
+ publisher_merkle_root: '0x0101',
275
+ calculation_alg: { checksum: '0x0202' },
276
+ timestamped_signature: {
277
+ timestamp: 999,
278
+ signature: { r: '0x0303', s: '0x0404', v: '27' },
279
+ },
280
+ },
281
+ })
282
+
283
+ expect(update?.id.length).toBe(32)
284
+ expect(update?.temporalNumericValueTimestampNs).toBe(999n)
285
+ })
286
+ })
287
+
288
+ describe('storkOracle', () => {
289
+ it('estimateStorkUpdateFeeMist scales per update', () => {
290
+ expect(estimateStorkUpdateFeeMist(2)).toBe(2n)
291
+ })
292
+
293
+ it('appendStorkUpdatesToTransaction adds move calls', () => {
294
+ const tx = new Transaction()
295
+ appendStorkUpdatesToTransaction(
296
+ tx,
297
+ {
298
+ storkPackage: '0x664fcc7d42abf7583938e6e64f51aa1ede063a49f445a6a9c0206638af0a53d9',
299
+ storkState: '0x88ca8f0ce0f6b30a39bdf71be27ffd0c5571adba28c49a1a3bd530e8fcffb29a',
300
+ },
301
+ [{
302
+ id: hexToBytes(SAMPLE_ID),
303
+ temporalNumericValueTimestampNs: 1n,
304
+ temporalNumericValueMagnitude: 1n,
305
+ temporalNumericValueNegative: false,
306
+ publisherMerkleRoot: hexToBytes('0x01'),
307
+ valueComputeAlgHash: hexToBytes('0x02'),
308
+ r: hexToBytes('0x03'),
309
+ s: hexToBytes('0x04'),
310
+ v: 27,
311
+ }],
312
+ )
313
+
314
+ expect(tx.getData().commands.length).toBe(3)
315
+ })
316
+ })