1
+ const sui = require ( "../helper/chain/sui" ) ;
2
+ const BigNumber = require ( "bignumber.js" ) ;
3
+ const { COIN_CONFIG , MMT_TYPE_CONFIG } = require ( "../nemo/coinConfig.js" ) ;
4
+ const { desU64} = require ( "../nemo/bytes" ) ;
5
+ const { getExchangeRate} = require ( "../nemo/price" ) ;
6
+ const { getVaultTvlByAmountB, getDynamicFieldObject} = require ( "../nemo/util" ) ;
7
+
8
+ const nemoPackageId = "0x2b71664477755b90f9fb71c9c944d5d0d3832fec969260e3f18efc7d855f57c4" ;
9
+ const syTableParentId = "0xcb74e46f4049e1afc3edcd77172ac6f9adfe1068cec6ca99ff6b80ca7879bd33" ;
10
+
11
+ const watchCoinType = [
12
+ '0xaafc4f740de0dd0dde642a31148fb94517087052f19afb0f7bed1dc41a50c77b::scallop_sui::SCALLOP_SUI' ,
13
+ '0x854950aa624b1df59fe64e630b2ba7c550642e9342267a33061d59fb31582da5::scallop_usdc::SCALLOP_USDC' ,
14
+ '0x5ca17430c1d046fae9edeaa8fd76c7b4193a00d764a0ecfa9418d733ad27bc1e::scallop_sca::SCALLOP_SCA' ,
15
+ '0xeb7a05a3224837c5e5503575aed0be73c091d1ce5e43aa3c3e716e0ae614608f::scallop_deep::SCALLOP_DEEP' ,
16
+ '0xb1d7df34829d1513b73ba17cb7ad90c88d1e104bb65ab8f62f13e0cc103783d3::scallop_sb_usdt::SCALLOP_SB_USDT' ,
17
+ '0xb14f82d8506d139eacef109688d1b71e7236bcce9b2c0ad526abcd6aa5be7de0::scallop_sb_eth::SCALLOP_SB_ETH' ,
18
+ '0xd285cbbf54c87fd93cd15227547467bb3e405da8bbf2ab99f83f323f88ac9a65::scallop_usdy::SCALLOP_USDY' ,
19
+ '0x0a228d1c59071eccf3716076a1f71216846ee256d9fb07ea11fb7c1eb56435a5::scallop_musd::SCALLOP_MUSD' ,
20
+ '0x622345b3f80ea5947567760eec7b9639d0582adcfd6ab9fccb85437aeda7c0d0::scallop_wal::SCALLOP_WAL' ,
21
+ '0xf325ce1300e8dac124071d3152c5c5ee6174914f8bc2161e88329cf579246efc::afsui::AFSUI' ,
22
+ '0xd1b72982e40348d069bb1ff701e634c117bb5f741f44dff91e472d3b01461e55::stsui::STSUI' ,
23
+ '0xd8b855d48fb4d8ffbb5c4a3ecac27b00f3712ce58626deb5a16a290e0c6edf84::nwal::NWAL' ,
24
+ '0x83556891f4a0f233ce7b05cfe7f957d4020492a34f5405b2cb9377d060bef4bf::spring_sui::SPRING_SUI' ,
25
+ '0x922d15d7f55c13fd790f6e54397470ec592caa2b508df292a2e8553f3d3b274f::msui::MSUI' ,
26
+ '0x502867b177303bf1bf226245fcdd3403c177e78d175a55a56c0602c7ff51c7fa::trevin_sui::TREVIN_SUI' ,
27
+ '0x41ff228bfd566f0c707173ee6413962a77e3929588d010250e4e76f0d1cc0ad4::ksui::KSUI' ,
28
+ '0x285b49635f4ed253967a2a4a5f0c5aea2cbd9dd0fc427b4086f3fad7ccef2c29::i_sui::I_SUI' ,
29
+ '0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT' ,
30
+ '0xd01d27939064d79e4ae1179cd11cfeeff23943f32b1a842ea1a1e15a0045d77d::st_sbuck::ST_SBUCK' ,
31
+ "0x7f29e761222a44b2141596e920edcc9049f8610f9d33f5354454d088e1f53b62::x_sui_sui_nevlp::X_SUI_SUI_NEVLP" ,
32
+ "0x295d7f569467934c934e6101284628ecbbb1e68d5c5baa8d4667ff09c42068ad::suiusdt_usdc_nevlp::SUIUSDT_USDC_NEVLP"
33
+ ] ;
34
+
35
+ const watchCoinTypeNotConvert = [
36
+ '0xf325ce1300e8dac124071d3152c5c5ee6174914f8bc2161e88329cf579246efc::afsui::AFSUI' ,
37
+ '0x790f258062909e3a0ffc78b3c53ac2f62d7084c3bab95644bdeb05add7250001::super_sui::SUPER_SUI' ,
38
+ '0xd1b72982e40348d069bb1ff701e634c117bb5f741f44dff91e472d3b01461e55::stsui::STSUI' ,
39
+ '0x83556891f4a0f233ce7b05cfe7f957d4020492a34f5405b2cb9377d060bef4bf::spring_sui::SPRING_SUI' ,
40
+ '0x02358129a7d66f943786a10b518fdc79145f1fc8d23420d9948c4aeea190f603::fud_sui::FUD_SUI' ,
41
+ '0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT' ,
42
+ ] ;
43
+
44
+ async function tvl ( api ) {
45
+ const marketIds = await sui . queryEvents ( {
46
+ eventType : `${ nemoPackageId } ::market_factory::MarketCreatedEvent` ,
47
+ transform : i => i . market_id
48
+ } ) ;
49
+
50
+ const markets = await sui . getObjects ( marketIds ) ;
51
+
52
+ for ( const market of markets ) {
53
+ if ( ! market ) continue ;
54
+
55
+ const { type, fields} = market ;
56
+ await getTvl ( type , fields , api ) ;
57
+ }
58
+ }
59
+
60
+ async function getTvl ( type , fields , api ) {
61
+ const typeString = type . replace ( ">" , "" ) . split ( "<" ) [ 1 ] ;
62
+ if ( ! typeString ) return null ;
63
+
64
+ const syTokens = typeString . split ( ", " ) [ 0 ] . slice ( 2 ) ;
65
+
66
+ const tokensObject = await getDynamicFieldObject (
67
+ syTableParentId , syTokens , { idType : "0x1::type_name::TypeName" } ) ;
68
+ if ( ! tokensObject || ! tokensObject . content ) return null ;
69
+
70
+ const tokens = "0x" + tokensObject . content . fields . value . fields . name ;
71
+
72
+ const coinConfig = COIN_CONFIG [ tokens ] ;
73
+
74
+ if ( ! coinConfig ) return null ;
75
+ if ( ! watchCoinType . includes ( coinConfig . coinType ) ) return null ;
76
+
77
+ const txBlockBytes = await getExchangeRate ( coinConfig ) ;
78
+
79
+ const inspectionResult = await sui . call (
80
+ 'sui_devInspectTransactionBlock' ,
81
+ [ '0x0000000000000000000000000000000000000000000000000000000000000000' ,
82
+ Buffer . from ( txBlockBytes ) . toString ( 'base64' ) ] ,
83
+ { withMetadata : true }
84
+ ) ;
85
+
86
+ if ( inspectionResult ?. effects ?. status ?. status !== 'success' ) {
87
+ return null ;
88
+ }
89
+
90
+ const returnValues = inspectionResult . results [ inspectionResult . results ?. length - 1 ] . returnValues ;
91
+ const res1 = returnValues [ 0 ] [ 0 ] ;
92
+ const res2 = returnValues [ 1 ] [ 0 ] ;
93
+ const priceVoucher1 = desU64 ( Uint8Array . from ( res1 ) ) ;
94
+ const priceVoucher2 = desU64 ( Uint8Array . from ( res2 ) ) ;
95
+
96
+ const pyState = await sui . getObject ( fields . py_state_id ) ;
97
+ const ptSupply = pyState . fields . pt_supply ;
98
+ const floatingPt = BigNumber ( ptSupply ) . minus ( fields . total_pt ) ;
99
+
100
+ if ( coinConfig . provider === 'Nemo' ) {
101
+ const pt2SyAmount = floatingPt . div ( priceVoucher1 ) . times ( priceVoucher2 ) ;
102
+
103
+ console . log ( `floatingPt: ${ floatingPt . toString ( ) } , ptSupply: ${ ptSupply } , pt2SyAmount: ${ pt2SyAmount . toString ( ) } , marketId: ${ fields . id . id } ` ) ;
104
+
105
+ const vault = await sui . getObject ( MMT_TYPE_CONFIG [ coinConfig . coinType ] . VAULT_ID ) ;
106
+ const amountB = await getVaultTvlByAmountB ( vault ) ;
107
+
108
+ const totalSupply = vault . fields . treasury_cap . fields . total_supply . fields . value ;
109
+
110
+ const lpTokenPrice = BigNumber ( amountB ) . div ( BigNumber ( totalSupply ) ) ;
111
+
112
+ console . log ( `lpTokenPrice: ${ lpTokenPrice . toString ( ) } , amountB: ${ amountB } , totalSupply: ${ totalSupply } ` ) ;
113
+
114
+ api . add ( coinConfig . underlyingCoinType , pt2SyAmount . times ( lpTokenPrice ) . toFixed ( 0 ) ) ;
115
+ } else {
116
+ let rate1 = new BigNumber ( priceVoucher1 ) . div ( new BigNumber ( 2 ) . pow ( 64 ) ) . toString ( ) ;
117
+ let rate2 = new BigNumber ( priceVoucher2 ) . div ( new BigNumber ( 2 ) . pow ( 64 ) ) . toString ( ) ;
118
+
119
+ const pt2SyAmount = floatingPt . div ( rate1 ) ;
120
+
121
+ if ( watchCoinTypeNotConvert . includes ( coinConfig . coinType ) ) {
122
+ api . add ( tokens , pt2SyAmount . toFixed ( 0 ) ) ;
123
+ } else {
124
+ let underlyingBalance = pt2SyAmount . multipliedBy ( rate2 ) ;
125
+ api . add ( coinConfig . underlyingCoinType , underlyingBalance . toFixed ( 0 ) ) ;
126
+ }
127
+ }
128
+ }
129
+
130
+ module . exports = {
131
+ timetravel : false ,
132
+ methodology : 'Count all floating PT assets in the Nemo markets.' ,
133
+ sui : {
134
+ tvl,
135
+ } ,
136
+ } ;
0 commit comments