JennieModule.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import { BaseClient } from './BaseClient'
  2. import { bcs, Coin, Coins, Fee, MsgExecute } from '@initia/initia.js'
  3. import { getAxiosClient } from './utils'
  4. export abstract class JennieModule extends BaseClient {
  5. protected constructor(mnemonic: string, useProxy: boolean = false) {
  6. super(mnemonic, useProxy)
  7. }
  8. async getXpAmount() {
  9. const viewResult = await this.lcd.move.viewFunction(
  10. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  11. 'initia_xp',
  12. 'get_xp_amount',
  13. undefined,
  14. [bcs.address().serialize(this.key.accAddress).toBase64()],
  15. )
  16. return viewResult
  17. }
  18. async drawFood() {
  19. const xp = await this.getXpAmount()
  20. if (Number(xp) < 200) {
  21. await this.claimableXp()
  22. return `done`
  23. }
  24. const msg = new MsgExecute(
  25. this.key.accAddress,
  26. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  27. 'jennie',
  28. 'draw_food',
  29. [],
  30. ['AQ=='],
  31. )
  32. return await this.broadcast(msg)
  33. }
  34. async feedJennie() {
  35. const viewResult: { hp: string; update_at: string } =
  36. await this.lcd.move.viewFunction(
  37. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  38. 'jennie',
  39. 'get_jennie_state',
  40. undefined,
  41. [bcs.address().serialize(this.key.accAddress).toBase64()],
  42. )
  43. // const stageInfo: {
  44. // current_stage: number
  45. // stage_interval: number
  46. // start_timestamp: number
  47. // } = await this.lcd.move.viewFunction(
  48. // '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  49. // 'jennie',
  50. // 'stage_info',
  51. // undefined,
  52. // [],
  53. // )
  54. const kt = Number(viewResult.update_at)
  55. const now = 1718354833
  56. // const currentStage = stageInfo.current_stage
  57. // const stageInternal = stageInfo.stage_interval
  58. // const stTimestamp = stageInfo.start_timestamp
  59. // const yt =
  60. // stTimestamp +
  61. // Math.floor(((currentStage ?? 1) - 1) / 7) * stageInternal * 7
  62. // const St =
  63. // stTimestamp +
  64. // (Math.floor(((currentStage ?? 1) - 1) / 7) + 1) * stageInternal * 7
  65. // const canFeed = kt < Math.floor(yt / 1000000)
  66. if (!(kt < now)) {
  67. return `done`
  68. }
  69. const rep = await getAxiosClient(true).get(
  70. `${this.rpcUrlUsing}initia/move/v1/accounts/${this.key.accAddress}/resources/by_struct_tag?struct_tag=0x9065fda28f52bb14ade545411f02e8e07a9cb4ba::jennie::FoodStore`,
  71. )
  72. const store = JSON.parse(rep.data.resource.move_resource)
  73. const data = store.data
  74. if (Number(data.tier1) > 0) {
  75. const msg = new MsgExecute(
  76. this.key.accAddress,
  77. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  78. 'jennie',
  79. 'feed_jennie',
  80. [],
  81. ['AQ=='],
  82. )
  83. return await this.broadcast(msg)
  84. } else if (Number(data.tier2) > 0) {
  85. const msg = new MsgExecute(
  86. this.key.accAddress,
  87. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  88. 'jennie',
  89. 'feed_jennie',
  90. [],
  91. [bcs.u8().serialize(2).toBase64()],
  92. )
  93. return await this.broadcast(msg)
  94. } else if (Number(data.tier3) > 0) {
  95. const msg = new MsgExecute(
  96. this.key.accAddress,
  97. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  98. 'jennie',
  99. 'feed_jennie',
  100. [],
  101. [bcs.u8().serialize(3).toBase64()],
  102. )
  103. return await this.broadcast(msg)
  104. } else {
  105. await this.drawFood()
  106. return `needFood`
  107. }
  108. }
  109. async mintJennie() {
  110. // Fetch mint progress details for 'jennie'
  111. const mintProgress: MintProgress = await this.lcd.move.viewFunction(
  112. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  113. 'jennie',
  114. 'get_jennie_mint_progress',
  115. [],
  116. [bcs.address().serialize(this.key.accAddress).toBase64()],
  117. )
  118. console.log(mintProgress)
  119. // Check if 'jennie' is already minted
  120. if (mintProgress.is_minted) {
  121. return `done`
  122. }
  123. // Initialize a flag to determine if all parts are minted
  124. let allPartsMinted = true
  125. // Iterate over each part progress
  126. for (const partProgress of mintProgress.jennie_part_progresses) {
  127. // If any part is not minted, set the flag to false
  128. if (!partProgress.is_minted) {
  129. allPartsMinted = false
  130. break // No need to check further parts
  131. }
  132. }
  133. // If not all parts are minted, exit the function
  134. if (!allPartsMinted) {
  135. return `undone`
  136. }
  137. // Prepare the minting message
  138. const msg = new MsgExecute(
  139. this.key.accAddress,
  140. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  141. 'jennie',
  142. 'mint_jennie',
  143. [],
  144. [],
  145. )
  146. // Broadcast the minting message
  147. return await this.broadcast(msg)
  148. }
  149. async mintPartApprovedAll() {
  150. const axios = getAxiosClient(true)
  151. const res = await axios.get(
  152. `https://xp-api.initiation-1.initia.xyz/xp/mint_parts/${this.key.accAddress}`,
  153. )
  154. const data = res.data
  155. let undone = [1, 2, 3, 4, 5, 6]
  156. for (const item of data) {
  157. const task = Number(item.task_id) + 1
  158. undone = undone.filter(value => value !== task)
  159. }
  160. console.log(undone)
  161. return undone
  162. }
  163. async mintPart() {
  164. // 获取 'jennie' 的铸造进度
  165. const axios = getAxiosClient(true)
  166. const res = await axios.get(
  167. `https://xp-api.initiation-1.initia.xyz/xp/mint_parts/${this.key.accAddress}`,
  168. )
  169. const data = res.data
  170. if (data.length !== 6) {
  171. return `undone`
  172. }
  173. const msgs = []
  174. const mintProgress: MintProgress = await this.lcd.move.viewFunction(
  175. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  176. 'jennie',
  177. 'get_jennie_mint_progress',
  178. [],
  179. [bcs.address().serialize(this.key.accAddress).toBase64()],
  180. )
  181. const progresses = mintProgress.jennie_part_progresses
  182. console.log(progresses)
  183. for (const item of progresses) {
  184. if (item.is_minted) {
  185. continue
  186. }
  187. for (let i = 0; i < data.length; i++) {
  188. if (Number(data[i].task_id) === Number(item.task)) {
  189. const sig = data[i]
  190. const msg = new MsgExecute(
  191. this.key.accAddress,
  192. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  193. 'jennie',
  194. 'mint_part_v2',
  195. [],
  196. [
  197. bcs.u8().serialize(sig.task_id).toBase64(),
  198. bcs
  199. .vector(bcs.u8())
  200. .serialize(Buffer.from(sig.signature, 'base64'))
  201. .toBase64(),
  202. ],
  203. )
  204. msgs.push(msg)
  205. }
  206. }
  207. }
  208. // 初始化消息数组
  209. if (msgs.length === 0) {
  210. return `done`
  211. }
  212. return await this.broadcast(msgs)
  213. }
  214. async claimableXp() {
  215. //https://xp-api.initiation-1.initia.xyz/xp/claimable/init1w6ftxlsv7y5putq955ymxh2kd0wru7nqshetka
  216. const res = getAxiosClient(true)
  217. const data = await res.get(
  218. `https://xp-api.initiation-1.initia.xyz/xp/claimable/${this.key.accAddress}`,
  219. )
  220. if (data.data.claimable_list.length > 0) {
  221. const proofs = data.data.claimable_list[0].merkle_proofs
  222. const proofsu8vec = proofs.map(p =>
  223. Uint8Array.from(Buffer.from(p, 'base64')),
  224. )
  225. const sd = bcs
  226. .vector(bcs.vector(bcs.u8()))
  227. .serialize(proofsu8vec)
  228. .toBase64()
  229. const msg = new MsgExecute(
  230. this.key.accAddress,
  231. '0x9065fda28f52bb14ade545411f02e8e07a9cb4ba',
  232. 'initia_xp',
  233. 'claim_point',
  234. [],
  235. [
  236. bcs.u64().serialize(data.data.claimable_list[0].stage).toBase64(),
  237. sd,
  238. bcs
  239. .u64()
  240. .serialize(data.data.claimable_list[0].task_point)
  241. .toBase64(),
  242. bcs
  243. .u64()
  244. .serialize(data.data.claimable_list[0].referral_point)
  245. .toBase64(),
  246. ],
  247. )
  248. const randLimit = 370000 + Math.floor(Math.random() * 10000)
  249. const signed = await this.wallet.createAndSignTx({
  250. msgs: Array.isArray(msg) ? msg : [msg],
  251. fee: new Fee(
  252. randLimit,
  253. new Coins([
  254. new Coin(
  255. 'move/944f8dd8dc49f96c25fea9849f16436dcfa6d564eec802f3ef7f8b3ea85368ff',
  256. randLimit / 2,
  257. ),
  258. ]),
  259. ),
  260. })
  261. const broadcast = await this.lcd.tx.broadcastAsync(signed)
  262. // console.log(broadcast.raw_log)
  263. // console.log(this.key.accAddress)
  264. return broadcast.txhash
  265. } else {
  266. return `done`
  267. }
  268. }
  269. }