index.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { getSignedVAA, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
  2. import { zeroPad } from "ethers/lib/utils";
  3. import { PublicKey } from "@solana/web3.js";
  4. let _P2W_WASM: any = undefined;
  5. async function importWasm() {
  6. if (!_P2W_WASM) {
  7. if (typeof window === 'undefined') {
  8. _P2W_WASM = await import("./solana/p2w-core/nodejs/p2w_sdk");
  9. } else {
  10. _P2W_WASM = await import("./solana/p2w-core/bundler/p2w_sdk");
  11. }
  12. }
  13. return _P2W_WASM;
  14. }
  15. export type Rational = {
  16. value: BigInt;
  17. numerator: BigInt;
  18. denominator: BigInt;
  19. };
  20. export type PriceAttestation = {
  21. productId: string;
  22. priceId: string;
  23. price: BigInt;
  24. conf: BigInt;
  25. expo: number;
  26. emaPrice: BigInt;
  27. emaConf: BigInt;
  28. status: number;
  29. numPublishers: BigInt;
  30. maxNumPublishers: BigInt;
  31. attestationTime: BigInt;
  32. publishTime: BigInt;
  33. prevPublishTime: BigInt;
  34. prevPrice: BigInt;
  35. prevConf: BigInt;
  36. };
  37. export type BatchPriceAttestation = {
  38. priceAttestations: PriceAttestation[];
  39. };
  40. export function rawToPriceAttestation(rawVal: any): PriceAttestation {
  41. return {
  42. productId: rawVal.product_id,
  43. priceId: rawVal.price_id,
  44. price: rawVal.price,
  45. conf: rawVal.conf,
  46. expo: rawVal.expo,
  47. emaPrice: rawVal.ema_price,
  48. emaConf: rawVal.ema_conf,
  49. status: rawVal.status,
  50. numPublishers: rawVal.num_publishers,
  51. maxNumPublishers: rawVal.max_num_publishers,
  52. attestationTime: rawVal.attestation_time,
  53. publishTime: rawVal.publish_time,
  54. prevPublishTime: rawVal.prev_publish_time,
  55. prevPrice: rawVal.prev_price,
  56. prevConf: rawVal.prev_conf,
  57. };
  58. }
  59. export async function parseBatchPriceAttestation(
  60. arr: Buffer
  61. ): Promise<BatchPriceAttestation> {
  62. let wasm = await importWasm();
  63. let rawVal = await wasm.parse_batch_attestation(arr);
  64. return rawVal;
  65. }
  66. // Returns a hash of all priceIds within the batch, it can be used to identify whether there is a
  67. // new batch with exact same symbols (and ignore the old one)
  68. export function getBatchAttestationHashKey(
  69. batchAttestation: BatchPriceAttestation
  70. ): string {
  71. const priceIds: string[] = batchAttestation.priceAttestations.map(
  72. (priceAttestation) => priceAttestation.priceId
  73. );
  74. priceIds.sort();
  75. return priceIds.join("#");
  76. }
  77. export function getBatchSummary(
  78. batch: BatchPriceAttestation
  79. ): string {
  80. let abstractRepresentation = {
  81. num_attestations: batch.priceAttestations.length,
  82. prices: batch.priceAttestations.map((priceAttestation) => {
  83. return {
  84. price_id: priceAttestation.priceId,
  85. price: computePrice(priceAttestation.price, priceAttestation.expo),
  86. conf: computePrice(
  87. priceAttestation.conf,
  88. priceAttestation.expo
  89. ),
  90. };
  91. }),
  92. };
  93. return JSON.stringify(abstractRepresentation);
  94. }
  95. export async function getSignedAttestation(host: string, p2w_addr: string, sequence: number, extraGrpcOpts = {}): Promise<any> {
  96. let [emitter, _] = await PublicKey.findProgramAddress([Buffer.from("p2w-emitter")], new PublicKey(p2w_addr));
  97. let emitterHex = sol_addr2buf(emitter).toString("hex");
  98. return await getSignedVAA(host, CHAIN_ID_SOLANA, emitterHex, "" + sequence, extraGrpcOpts);
  99. }
  100. function computePrice(rawPrice: BigInt, expo: number): number {
  101. return Number(rawPrice) * 10 ** expo;
  102. }
  103. function sol_addr2buf(addr: PublicKey): Buffer {
  104. return Buffer.from(zeroPad(addr.toBytes(), 32));
  105. }