PythTest.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import {
  2. Address,
  3. beginCell,
  4. Cell,
  5. Contract,
  6. contractAddress,
  7. ContractProvider,
  8. Dictionary,
  9. Sender,
  10. SendMode,
  11. } from "@ton/core";
  12. import { HexString, Price } from "@pythnetwork/price-service-sdk";
  13. export type PythTestConfig = {
  14. priceFeedId: HexString;
  15. timePeriod: number;
  16. price: Price;
  17. emaPrice: Price;
  18. };
  19. export class PythTest implements Contract {
  20. constructor(
  21. readonly address: Address,
  22. readonly init?: { code: Cell; data: Cell }
  23. ) {}
  24. static createFromAddress(address: Address) {
  25. return new PythTest(address);
  26. }
  27. static createFromConfig(config: PythTestConfig, code: Cell, workchain = 0) {
  28. const data = PythTest.getPythInitData(
  29. config.priceFeedId,
  30. config.timePeriod,
  31. config.price,
  32. config.emaPrice
  33. );
  34. const init = { code, data };
  35. return new PythTest(contractAddress(workchain, init), init);
  36. }
  37. static getPythInitData(
  38. priceFeedId: HexString,
  39. timePeriod: number,
  40. price: Price,
  41. emaPrice: Price
  42. ): Cell {
  43. const priceDict = Dictionary.empty(
  44. Dictionary.Keys.BigUint(256),
  45. Dictionary.Values.Cell()
  46. );
  47. const priceCell = beginCell()
  48. .storeInt(price.getPriceAsNumberUnchecked() * 10 ** -price.expo, 256)
  49. .storeUint(price.getConfAsNumberUnchecked() * 10 ** -price.expo, 64)
  50. .storeInt(price.expo, 32)
  51. .storeUint(price.publishTime, 64)
  52. .endCell();
  53. const emaPriceCell = beginCell()
  54. .storeInt(
  55. emaPrice.getPriceAsNumberUnchecked() * 10 ** -emaPrice.expo,
  56. 256
  57. )
  58. .storeUint(emaPrice.getConfAsNumberUnchecked() * 10 ** -emaPrice.expo, 64)
  59. .storeInt(emaPrice.expo, 32)
  60. .storeUint(emaPrice.publishTime, 64)
  61. .endCell();
  62. const priceFeedCell = beginCell()
  63. .storeRef(priceCell)
  64. .storeRef(emaPriceCell)
  65. .storeUint(timePeriod, 32)
  66. .endCell();
  67. priceDict.set(BigInt(priceFeedId), priceFeedCell);
  68. return beginCell()
  69. .storeDict(priceDict) // latest_price_feeds
  70. .storeUint(0, 32)
  71. .storeDict(Dictionary.empty())
  72. .storeUint(0, 16)
  73. .storeUint(0, 16)
  74. .storeBuffer(
  75. Buffer.from(
  76. "0000000000000000000000000000000000000000000000000000000000000000",
  77. "hex"
  78. )
  79. )
  80. .storeDict(Dictionary.empty()) // consumed_governance_actions,
  81. .endCell();
  82. }
  83. async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
  84. await provider.internal(via, {
  85. value,
  86. sendMode: SendMode.PAY_GAS_SEPARATELY,
  87. body: beginCell().endCell(),
  88. });
  89. }
  90. async getPriceUnsafe(provider: ContractProvider, priceFeedId: HexString) {
  91. const result = await provider.get("test_price_unsafe", [
  92. { type: "int", value: BigInt(priceFeedId) },
  93. ]);
  94. const price = result.stack.readNumber();
  95. const conf = result.stack.readNumber();
  96. const expo = result.stack.readNumber();
  97. const publishTime = result.stack.readNumber();
  98. return {
  99. price,
  100. conf,
  101. expo,
  102. publishTime,
  103. };
  104. }
  105. async getPriceNoOlderThan(
  106. provider: ContractProvider,
  107. timePeriod: number,
  108. priceFeedId: HexString
  109. ) {
  110. const result = await provider.get("test_price_no_older_than", [
  111. { type: "int", value: BigInt(timePeriod) },
  112. { type: "int", value: BigInt(priceFeedId) },
  113. ]);
  114. const price = result.stack.readNumber();
  115. const conf = result.stack.readNumber();
  116. const expo = result.stack.readNumber();
  117. const publishTime = result.stack.readNumber();
  118. return {
  119. price,
  120. conf,
  121. expo,
  122. publishTime,
  123. };
  124. }
  125. async getEmaPriceUnsafe(provider: ContractProvider, priceFeedId: HexString) {
  126. const result = await provider.get("test_ema_price_unsafe", [
  127. { type: "int", value: BigInt(priceFeedId) },
  128. ]);
  129. const price = result.stack.readNumber();
  130. const conf = result.stack.readNumber();
  131. const expo = result.stack.readNumber();
  132. const publishTime = result.stack.readNumber();
  133. return {
  134. price,
  135. conf,
  136. expo,
  137. publishTime,
  138. };
  139. }
  140. async getEmaPriceNoOlderThan(
  141. provider: ContractProvider,
  142. timePeriod: number,
  143. priceFeedId: HexString
  144. ) {
  145. const result = await provider.get("test_ema_price_no_older_than", [
  146. { type: "int", value: BigInt(timePeriod) },
  147. { type: "int", value: BigInt(priceFeedId) },
  148. ]);
  149. const price = result.stack.readNumber();
  150. const conf = result.stack.readNumber();
  151. const expo = result.stack.readNumber();
  152. const publishTime = result.stack.readNumber();
  153. return {
  154. price,
  155. conf,
  156. expo,
  157. publishTime,
  158. };
  159. }
  160. }