Bläddra i källkod

Merge pull request #44 from pyth-network/abehjati/p2w-sdk-rust

Add p2w rust sdk
Ali Behjati 3 år sedan
förälder
incheckning
186e79c334

+ 1124 - 0
third_party/pyth/p2w-sdk/rust/Cargo.lock

@@ -0,0 +1,1124 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ahash"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "arrayref"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "base64"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+
+[[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "blake3"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+ "digest 0.10.3",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "block-padding",
+ "generic-array",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
+
+[[package]]
+name = "borsh"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18dda7dc709193c0d86a1a51050a926dc3df1cf262ec46a23a25dba421ea1924"
+dependencies = [
+ "borsh-derive",
+ "hashbrown",
+]
+
+[[package]]
+name = "borsh-derive"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "684155372435f578c0fa1acd13ebbb182cc19d6b38b64ae7901da4393217d264"
+dependencies = [
+ "borsh-derive-internal",
+ "borsh-schema-derive-internal",
+ "proc-macro-crate",
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "borsh-derive-internal"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2102f62f8b6d3edeab871830782285b64cc1830168094db05c8e458f209bc5c3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "borsh-schema-derive-internal"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "196c978c4c9b0b142d446ef3240690bf5a8a33497074a113ff9a337ccb750483"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "bs58"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
+
+[[package]]
+name = "bumpalo"
+version = "3.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
+
+[[package]]
+name = "bv"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340"
+dependencies = [
+ "feature-probe",
+ "serde",
+]
+
+[[package]]
+name = "bytemuck"
+version = "1.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cc"
+version = "1.0.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "console_error_panic_hook"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "console_log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494"
+dependencies = [
+ "log",
+ "web-sys",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "crypto-common"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "crypto-mac"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
+dependencies = [
+ "generic-array",
+ "subtle",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "3.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"
+dependencies = [
+ "byteorder",
+ "digest 0.9.0",
+ "rand_core",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
+dependencies = [
+ "block-buffer 0.10.2",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "env_logger"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "feature-probe"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da"
+
+[[package]]
+name = "generic-array"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
+dependencies = [
+ "serde",
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hmac"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840"
+dependencies = [
+ "crypto-mac",
+ "digest 0.9.0",
+]
+
+[[package]]
+name = "hmac-drbg"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1"
+dependencies = [
+ "digest 0.9.0",
+ "generic-array",
+ "hmac",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
+
+[[package]]
+name = "js-sys"
+version = "0.3.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.119"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
+
+[[package]]
+name = "libsecp256k1"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73"
+dependencies = [
+ "arrayref",
+ "base64 0.12.3",
+ "digest 0.9.0",
+ "hmac-drbg",
+ "libsecp256k1-core",
+ "libsecp256k1-gen-ecmult",
+ "libsecp256k1-gen-genmult",
+ "rand",
+ "serde",
+ "sha2",
+ "typenum",
+]
+
+[[package]]
+name = "libsecp256k1-core"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80"
+dependencies = [
+ "crunchy",
+ "digest 0.9.0",
+ "subtle",
+]
+
+[[package]]
+name = "libsecp256k1-gen-ecmult"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3"
+dependencies = [
+ "libsecp256k1-core",
+]
+
+[[package]]
+name = "libsecp256k1-gen-genmult"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d"
+dependencies = [
+ "libsecp256k1-core",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "memmap2"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "num-derive"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "p2w-sdk"
+version = "0.1.0"
+dependencies = [
+ "pyth-client",
+ "serde",
+ "solana-program",
+ "solitaire",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "proc-macro-crate"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
+dependencies = [
+ "toml",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "pyth-client"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f779e98b8c8016d0c1409247a204bd4fcdea8b67ceeef545f04e324d66c49e52"
+dependencies = [
+ "borsh",
+ "borsh-derive",
+ "bytemuck",
+ "num-derive",
+ "num-traits",
+ "serde",
+ "solana-program",
+ "thiserror",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+
+[[package]]
+name = "rocksalt"
+version = "0.1.0"
+dependencies = [
+ "byteorder",
+ "proc-macro2",
+ "quote",
+ "sha3",
+ "solana-program",
+ "syn",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+
+[[package]]
+name = "ryu"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "semver"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
+
+[[package]]
+name = "serde"
+version = "1.0.136"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_bytes"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.136"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha2"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
+dependencies = [
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
+[[package]]
+name = "sha3"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809"
+dependencies = [
+ "block-buffer 0.9.0",
+ "digest 0.9.0",
+ "keccak",
+ "opaque-debug",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+
+[[package]]
+name = "solana-frozen-abi"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c89bcde59ac3e8d4dbf7c4d990b0627b8ca0d25394c4ce17896dde7a1452e40c"
+dependencies = [
+ "bs58",
+ "bv",
+ "generic-array",
+ "log",
+ "memmap2",
+ "rustc_version",
+ "serde",
+ "serde_derive",
+ "sha2",
+ "solana-frozen-abi-macro",
+ "solana-logger",
+ "thiserror",
+]
+
+[[package]]
+name = "solana-frozen-abi-macro"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56a7d630da35993631ecc4dd155f92d0d58000cdde3d5e2764fe9fd49d20a3a8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn",
+]
+
+[[package]]
+name = "solana-logger"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eaf925bb665de46f96fcea2c8a900d0d870a96fd1f50cf2bad16e22a1da71c4"
+dependencies = [
+ "env_logger",
+ "lazy_static",
+ "log",
+]
+
+[[package]]
+name = "solana-program"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fc4d7a0baa649a3bda06d6a1cc30bd3d8ac692702a75fa8e76369cf7b3f6329"
+dependencies = [
+ "base64 0.13.0",
+ "bincode",
+ "bitflags",
+ "blake3",
+ "borsh",
+ "borsh-derive",
+ "bs58",
+ "bv",
+ "bytemuck",
+ "console_error_panic_hook",
+ "console_log",
+ "curve25519-dalek",
+ "getrandom",
+ "itertools",
+ "js-sys",
+ "lazy_static",
+ "libsecp256k1",
+ "log",
+ "num-derive",
+ "num-traits",
+ "parking_lot",
+ "rand",
+ "rustc_version",
+ "rustversion",
+ "serde",
+ "serde_bytes",
+ "serde_derive",
+ "sha2",
+ "sha3",
+ "solana-frozen-abi",
+ "solana-frozen-abi-macro",
+ "solana-logger",
+ "solana-sdk-macro",
+ "thiserror",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "solana-sdk-macro"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec22a924c73abe3376a2046715a2f6a9ae4094095b8ea08e8e56e8de198264ad"
+dependencies = [
+ "bs58",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
+name = "solitaire"
+version = "0.1.0"
+dependencies = [
+ "borsh",
+ "byteorder",
+ "rocksalt",
+ "sha3",
+ "solana-program",
+]
+
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "syn"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "typenum"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
+dependencies = [
+ "cfg-if",
+ "serde",
+ "serde_json",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
+dependencies = [
+ "bumpalo",
+ "lazy_static",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
+
+[[package]]
+name = "web-sys"
+version = "0.3.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "zeroize"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"

+ 20 - 0
third_party/pyth/p2w-sdk/rust/Cargo.toml

@@ -0,0 +1,20 @@
+[package]
+name = "p2w-sdk"
+version = "0.1.0"
+authors = ["Wormhole Contributors <contact@certus.one>"]
+edition = "2018"
+description = "Pyth to Wormhole SDK"
+
+
+[lib]
+crate-type = ["cdylib", "rlib"]
+
+[features]
+wasm = ["wasm-bindgen"]
+
+[dependencies]
+serde = { version = "1.0.103", default-features = false, features = ["derive"] }
+pyth-client = { version = "0.5.0", features = ["no-entrypoint"] }
+wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"], optional = true}
+solitaire = { path = "../../../../solana/solitaire/program" }
+solana-program = "1.8.16"

+ 4 - 0
third_party/pyth/p2w-sdk/rust/README.md

@@ -0,0 +1,4 @@
+# P2W SDK
+
+## Development
+This crate requires rust nightly to compile.

+ 18 - 0
third_party/pyth/p2w-sdk/rust/rustfmt.toml

@@ -0,0 +1,18 @@
+# Merge similar crates together to avoid multiple use statements.
+imports_granularity = "Module"
+
+# Consistency in formatting makes tool based searching/editing better.
+empty_item_single_line = false
+
+# Easier editing when arbitrary mixed use statements do not collapse.
+imports_layout = "Vertical"
+
+# Default rustfmt formatting of match arms with branches is awful.
+match_arm_leading_pipes = "Preserve"
+
+# Align Fields
+enum_discrim_align_threshold = 80
+struct_field_align_threshold = 80
+
+# Allow up to two blank lines for grouping.
+blank_lines_upper_bound = 2

+ 535 - 0
third_party/pyth/p2w-sdk/rust/src/lib.rs

@@ -0,0 +1,535 @@
+//! Constants and values common to every p2w custom-serialized message.
+//!
+//! The format makes no attempt to provide human-readable symbol names
+//! in favor of explicit product/price Solana account addresses
+//! (IDs). This choice was made to disambiguate any symbols with
+//! similar human-readable names and provide a failsafe for some of
+//! the probable adversarial scenarios.
+
+use std::borrow::Borrow;
+use std::convert::TryInto;
+use std::io::Read;
+use std::iter::Iterator;
+use std::mem;
+
+use pyth_client::{
+    CorpAction,
+    Ema,
+    PriceStatus,
+    PriceType,
+};
+
+use solitaire::{
+    Derive,
+    Info,
+};
+
+use solana_program::clock::UnixTimestamp;
+use solana_program::pubkey::Pubkey;
+
+#[cfg(feature = "wasm")]
+#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
+pub mod wasm;
+
+/// Quality of life type alias for wrapping up boxed errors.
+pub type ErrBox = Box<dyn std::error::Error>;
+
+/// Precedes every message implementing the p2w serialization format
+pub const P2W_MAGIC: &'static [u8] = b"P2WH";
+
+/// Format version used and understood by this codebase
+pub const P2W_FORMAT_VERSION: u16 = 2;
+
+pub const PUBKEY_LEN: usize = 32;
+
+/// Emmitter Address to wormhole is a PDA with seed p2w-emmiter from attestation contract
+pub type P2WEmitter<'b> = Derive<Info<'b>, "p2w-emitter">;
+
+/// Decides the format of following bytes
+#[repr(u8)]
+pub enum PayloadId {
+    PriceAttestation      = 1, // Not in use, currently batch attestations imply PriceAttestation messages inside
+    PriceBatchAttestation = 2,
+}
+
+// On-chain data types
+
+/// The main attestation data type.
+///
+/// Important: For maximum security, *both* product_id and price_id
+/// should be used as storage keys for known attestations in target
+/// chain logic.
+#[derive(Clone, Default, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PriceAttestation {
+    pub product_id:          Pubkey,
+    pub price_id:            Pubkey,
+    pub price_type:          PriceType,
+    pub price:               i64,
+    pub expo:                i32,
+    pub twap:                Ema,
+    pub twac:                Ema,
+    pub confidence_interval: u64,
+    pub status:              PriceStatus,
+    pub corp_act:            CorpAction,
+    pub timestamp:           UnixTimestamp,
+}
+
+#[derive(Clone, Default, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct BatchPriceAttestation {
+    pub price_attestations: Vec<PriceAttestation>,
+}
+
+impl BatchPriceAttestation {
+    /// Turn a bunch of attestations into a combined payload.
+    ///
+    /// Batches assume constant-size attestations within a single batch.
+    pub fn serialize(&self) -> Result<Vec<u8>, ErrBox> {
+        // magic
+        let mut buf = P2W_MAGIC.to_vec();
+
+        // version
+        buf.extend_from_slice(&P2W_FORMAT_VERSION.to_be_bytes()[..]);
+
+        // payload_id
+        buf.push(PayloadId::PriceBatchAttestation as u8);
+
+        // n_attestations
+        buf.extend_from_slice(&(self.price_attestations.len() as u16).to_be_bytes()[..]);
+
+        let mut attestation_size = 0; // Will be determined as we serialize attestations
+        let mut serialized_attestations = Vec::with_capacity(self.price_attestations.len());
+        for (idx, a) in self.price_attestations.iter().enumerate() {
+            // Learn the current attestation's size
+            let serialized = PriceAttestation::serialize(a.borrow());
+            let a_len = serialized.len();
+
+            // Verify it's the same as the first one we saw for the batch, assign if we're first.
+            if attestation_size > 0 {
+                if a_len != attestation_size {
+                    return Err(format!(
+                        "attestation {} serializes to {} bytes, {} expected",
+                        idx + 1,
+                        a_len,
+                        attestation_size
+                    )
+                    .into());
+                }
+            } else {
+                attestation_size = a_len;
+            }
+
+            serialized_attestations.push(serialized);
+        }
+
+        // attestation_size
+        buf.extend_from_slice(&(attestation_size as u16).to_be_bytes()[..]);
+
+        for mut s in serialized_attestations.into_iter() {
+            buf.append(&mut s)
+        }
+
+        Ok(buf)
+    }
+
+    pub fn deserialize(mut bytes: impl Read) -> Result<Self, ErrBox> {
+        let mut magic_vec = vec![0u8; P2W_MAGIC.len()];
+        bytes.read_exact(magic_vec.as_mut_slice())?;
+
+        if magic_vec.as_slice() != P2W_MAGIC {
+            return Err(format!(
+                "Invalid magic {:02X?}, expected {:02X?}",
+                magic_vec, P2W_MAGIC,
+            )
+            .into());
+        }
+
+        let mut version_vec = vec![0u8; mem::size_of_val(&P2W_FORMAT_VERSION)];
+        bytes.read_exact(version_vec.as_mut_slice())?;
+        let version = u16::from_be_bytes(version_vec.as_slice().try_into()?);
+
+        if version != P2W_FORMAT_VERSION {
+            return Err(format!(
+                "Unsupported format version {}, expected {}",
+                version, P2W_FORMAT_VERSION
+            )
+            .into());
+        }
+
+        let mut payload_id_vec = vec![0u8; mem::size_of::<PayloadId>()];
+        bytes.read_exact(payload_id_vec.as_mut_slice())?;
+
+        if payload_id_vec[0] != PayloadId::PriceBatchAttestation as u8 {
+            return Err(format!(
+                "Invalid Payload ID {}, expected {}",
+                payload_id_vec[0],
+                PayloadId::PriceBatchAttestation as u8,
+            )
+            .into());
+        }
+
+        let mut batch_len_vec = vec![0u8; 2];
+        bytes.read_exact(batch_len_vec.as_mut_slice())?;
+        let batch_len = u16::from_be_bytes(batch_len_vec.as_slice().try_into()?);
+
+        let mut attestation_size_vec = vec![0u8; 2];
+        bytes.read_exact(attestation_size_vec.as_mut_slice())?;
+        let attestation_size = u16::from_be_bytes(attestation_size_vec.as_slice().try_into()?);
+
+        let mut ret = Vec::with_capacity(batch_len as usize);
+
+        for i in 0..batch_len {
+            let mut attestation_buf = vec![0u8; attestation_size as usize];
+            bytes.read_exact(attestation_buf.as_mut_slice())?;
+
+            dbg!(&attestation_buf.len());
+
+            match PriceAttestation::deserialize(attestation_buf.as_slice()) {
+                Ok(attestation) => ret.push(attestation),
+                Err(e) => {
+                    return Err(format!("PriceAttestation {}/{}: {}", i + 1, batch_len, e).into())
+                }
+            }
+        }
+
+        Ok(Self {
+            price_attestations: ret,
+        })
+    }
+}
+
+pub fn serialize_ema(ema: &Ema) -> Vec<u8> {
+    let mut v = vec![];
+    // val
+    v.extend(&ema.val.to_be_bytes()[..]);
+
+    // numer
+    v.extend(&ema.numer.to_be_bytes()[..]);
+
+    // denom
+    v.extend(&ema.denom.to_be_bytes()[..]);
+
+    v
+}
+
+pub fn deserialize_ema(mut bytes: impl Read) -> Result<Ema, ErrBox> {
+    let mut val_vec = vec![0u8; mem::size_of::<i64>()];
+    bytes.read_exact(val_vec.as_mut_slice())?;
+    let val = i64::from_be_bytes(val_vec.as_slice().try_into()?);
+
+    let mut numer_vec = vec![0u8; mem::size_of::<i64>()];
+    bytes.read_exact(numer_vec.as_mut_slice())?;
+    let numer = i64::from_be_bytes(numer_vec.as_slice().try_into()?);
+
+    let mut denom_vec = vec![0u8; mem::size_of::<i64>()];
+    bytes.read_exact(denom_vec.as_mut_slice())?;
+    let denom = i64::from_be_bytes(denom_vec.as_slice().try_into()?);
+
+    Ok(Ema { val, numer, denom })
+}
+
+// On-chain data types
+
+impl PriceAttestation {
+    pub fn from_pyth_price_bytes(
+        price_id: Pubkey,
+        timestamp: UnixTimestamp,
+        value: &[u8],
+    ) -> Result<Self, ErrBox> {
+        let price = pyth_client::load_price(value)?;
+
+        Ok(PriceAttestation {
+            product_id: Pubkey::new(&price.prod.val[..]),
+            price_id,
+            price_type: price.ptype,
+            price: price.agg.price,
+            twap: price.twap,
+            twac: price.twac,
+            expo: price.expo,
+            confidence_interval: price.agg.conf,
+            status: price.agg.status,
+            corp_act: price.agg.corp_act,
+            timestamp: timestamp,
+        })
+    }
+
+    /// Serialize this attestation according to the Pyth-over-wormhole serialization format
+    pub fn serialize(&self) -> Vec<u8> {
+        // A nifty trick to get us yelled at if we forget to serialize a field
+        #[deny(warnings)]
+        let PriceAttestation {
+            product_id,
+            price_id,
+            price_type,
+            price,
+            expo,
+            twap,
+            twac,
+            confidence_interval,
+            status,
+            corp_act,
+            timestamp,
+        } = self;
+
+        // magic
+        let mut buf = P2W_MAGIC.to_vec();
+
+        // version
+        buf.extend_from_slice(&P2W_FORMAT_VERSION.to_be_bytes()[..]);
+
+        // payload_id
+        buf.push(PayloadId::PriceAttestation as u8);
+
+        // product_id
+        buf.extend_from_slice(&product_id.to_bytes()[..]);
+
+        // price_id
+        buf.extend_from_slice(&price_id.to_bytes()[..]);
+
+        // price_type
+        buf.push(price_type.clone() as u8);
+
+        // price
+        buf.extend_from_slice(&price.to_be_bytes()[..]);
+
+        // exponent
+        buf.extend_from_slice(&expo.to_be_bytes()[..]);
+
+        // twap
+        buf.append(&mut serialize_ema(&twap));
+
+        // twac
+        buf.append(&mut serialize_ema(&twac));
+
+        // confidence_interval
+        buf.extend_from_slice(&confidence_interval.to_be_bytes()[..]);
+
+        // status
+        buf.push(status.clone() as u8);
+
+        // corp_act
+        buf.push(corp_act.clone() as u8);
+
+        // timestamp
+        buf.extend_from_slice(&timestamp.to_be_bytes()[..]);
+
+        buf
+    }
+    pub fn deserialize(mut bytes: impl Read) -> Result<Self, ErrBox> {
+        let mut magic_vec = vec![0u8; P2W_MAGIC.len()];
+
+        bytes.read_exact(magic_vec.as_mut_slice())?;
+
+        if magic_vec.as_slice() != P2W_MAGIC {
+            return Err(format!(
+                "Invalid magic {:02X?}, expected {:02X?}",
+                magic_vec, P2W_MAGIC,
+            )
+            .into());
+        }
+
+        let mut version_vec = vec![0u8; mem::size_of_val(&P2W_FORMAT_VERSION)];
+        bytes.read_exact(version_vec.as_mut_slice())?;
+        let version = u16::from_be_bytes(version_vec.as_slice().try_into()?);
+
+        if version != P2W_FORMAT_VERSION {
+            return Err(format!(
+                "Unsupported format version {}, expected {}",
+                version, P2W_FORMAT_VERSION
+            )
+            .into());
+        }
+
+        let mut payload_id_vec = vec![0u8; mem::size_of::<PayloadId>()];
+        bytes.read_exact(payload_id_vec.as_mut_slice())?;
+
+        if PayloadId::PriceAttestation as u8 != payload_id_vec[0] {
+            return Err(format!(
+                "Invalid Payload ID {}, expected {}",
+                payload_id_vec[0],
+                PayloadId::PriceAttestation as u8,
+            )
+            .into());
+        }
+
+        let mut product_id_vec = vec![0u8; PUBKEY_LEN];
+        bytes.read_exact(product_id_vec.as_mut_slice())?;
+        let product_id = Pubkey::new(product_id_vec.as_slice());
+
+        let mut price_id_vec = vec![0u8; PUBKEY_LEN];
+        bytes.read_exact(price_id_vec.as_mut_slice())?;
+        let price_id = Pubkey::new(price_id_vec.as_slice());
+
+        let mut price_type_vec = vec![0u8];
+        bytes.read_exact(price_type_vec.as_mut_slice())?;
+        let price_type = match price_type_vec[0] {
+            a if a == PriceType::Price as u8 => PriceType::Price,
+            a if a == PriceType::Unknown as u8 => PriceType::Unknown,
+            other => {
+                return Err(format!("Invalid price_type value {}", other).into());
+            }
+        };
+
+        let mut price_vec = vec![0u8; mem::size_of::<i64>()];
+        bytes.read_exact(price_vec.as_mut_slice())?;
+        let price = i64::from_be_bytes(price_vec.as_slice().try_into()?);
+
+        let mut expo_vec = vec![0u8; mem::size_of::<i32>()];
+        bytes.read_exact(expo_vec.as_mut_slice())?;
+        let expo = i32::from_be_bytes(expo_vec.as_slice().try_into()?);
+
+        let twap = deserialize_ema(&mut bytes)?;
+        let twac = deserialize_ema(&mut bytes)?;
+
+        println!("twac OK");
+        let mut confidence_interval_vec = vec![0u8; mem::size_of::<u64>()];
+        bytes.read_exact(confidence_interval_vec.as_mut_slice())?;
+        let confidence_interval =
+            u64::from_be_bytes(confidence_interval_vec.as_slice().try_into()?);
+
+        let mut status_vec = vec![0u8];
+        bytes.read_exact(status_vec.as_mut_slice())?;
+        let status = match status_vec[0] {
+            a if a == PriceStatus::Unknown as u8 => PriceStatus::Unknown,
+            a if a == PriceStatus::Trading as u8 => PriceStatus::Trading,
+            a if a == PriceStatus::Halted as u8 => PriceStatus::Halted,
+            a if a == PriceStatus::Auction as u8 => PriceStatus::Auction,
+            other => {
+                return Err(format!("Invalid status value {}", other).into());
+            }
+        };
+
+        let mut corp_act_vec = vec![0u8];
+        bytes.read_exact(corp_act_vec.as_mut_slice())?;
+        let corp_act = match corp_act_vec[0] {
+            a if a == CorpAction::NoCorpAct as u8 => CorpAction::NoCorpAct,
+            other => {
+                return Err(format!("Invalid corp_act value {}", other).into());
+            }
+        };
+
+        let mut timestamp_vec = vec![0u8; mem::size_of::<UnixTimestamp>()];
+        bytes.read_exact(timestamp_vec.as_mut_slice())?;
+        let timestamp = UnixTimestamp::from_be_bytes(timestamp_vec.as_slice().try_into()?);
+
+        Ok(Self {
+            product_id,
+            price_id,
+            price_type,
+            price,
+            expo,
+            twap,
+            twac,
+            confidence_interval,
+            status,
+            corp_act,
+            timestamp,
+        })
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use pyth_client::{
+        Ema,
+        PriceStatus,
+        PriceType,
+    };
+
+    fn mock_attestation(prod: Option<[u8; 32]>, price: Option<[u8; 32]>) -> PriceAttestation {
+        let product_id_bytes = prod.unwrap_or([21u8; 32]);
+        let price_id_bytes = price.unwrap_or([222u8; 32]);
+        PriceAttestation {
+            product_id:          Pubkey::new_from_array(product_id_bytes),
+            price_id:            Pubkey::new_from_array(price_id_bytes),
+            price:               (0xdeadbeefdeadbabe as u64) as i64,
+            price_type:          PriceType::Price,
+            twap:                Ema {
+                val:   -42,
+                numer: 15,
+                denom: 37,
+            },
+            twac:                Ema {
+                val:   42,
+                numer: 1111,
+                denom: 2222,
+            },
+            expo:                -3,
+            status:              PriceStatus::Trading,
+            confidence_interval: 101,
+            corp_act:            CorpAction::NoCorpAct,
+            timestamp:           123456789i64,
+        }
+    }
+
+    #[test]
+    fn test_attestation_serde() -> Result<(), ErrBox> {
+        let product_id_bytes = [21u8; 32];
+        let price_id_bytes = [222u8; 32];
+        let attestation: PriceAttestation =
+            mock_attestation(Some(product_id_bytes), Some(price_id_bytes));
+
+        println!("Hex product_id: {:02X?}", &product_id_bytes);
+        println!("Hex price_id: {:02X?}", &price_id_bytes);
+
+        println!("Regular: {:#?}", &attestation);
+        println!("Hex: {:#02X?}", &attestation);
+        let bytes = attestation.serialize();
+        println!("Hex Bytes: {:02X?}", bytes);
+
+        assert_eq!(
+            PriceAttestation::deserialize(bytes.as_slice())?,
+            attestation
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn test_attestation_serde_wrong_size() -> Result<(), ErrBox> {
+        assert!(PriceAttestation::deserialize(&[][..]).is_err());
+        assert!(PriceAttestation::deserialize(vec![0u8; 1].as_slice()).is_err());
+        Ok(())
+    }
+
+    #[test]
+    fn test_batch_serde() -> Result<(), ErrBox> {
+        let attestations: Vec<_> = (0..65535)
+            .map(|i| mock_attestation(Some([(i % 256) as u8; 32]), None))
+            .collect();
+
+        let batch_attestation = BatchPriceAttestation {
+            price_attestations: attestations,
+        };
+
+        let serialized = batch_attestation.serialize()?;
+
+        let deserialized: BatchPriceAttestation =
+            BatchPriceAttestation::deserialize(serialized.as_slice())?;
+
+        assert_eq!(batch_attestation, deserialized);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_batch_serde_wrong_size() -> Result<(), ErrBox> {
+        assert!(BatchPriceAttestation::deserialize(&[][..]).is_err());
+        assert!(BatchPriceAttestation::deserialize(vec![0u8; 1].as_slice()).is_err());
+
+        let attestations: Vec<_> = (0..20)
+            .map(|i| mock_attestation(Some([(i % 256) as u8; 32]), None))
+            .collect();
+
+        let batch_attestation = BatchPriceAttestation {
+            price_attestations: attestations,
+        };
+
+        let serialized = batch_attestation.serialize()?;
+
+        // Missing last byte in last attestation must be an error
+        let len = serialized.len();
+        assert!(BatchPriceAttestation::deserialize(&serialized.as_slice()[..len - 1]).is_err());
+
+        Ok(())
+    }
+}

+ 33 - 0
third_party/pyth/p2w-sdk/rust/src/wasm.rs

@@ -0,0 +1,33 @@
+use solana_program::pubkey::Pubkey;
+use solitaire::Seeded;
+use std::str::FromStr;
+use wasm_bindgen::prelude::*;
+
+
+use crate::{
+    BatchPriceAttestation,
+    P2WEmitter,
+    PriceAttestation,
+};
+
+#[wasm_bindgen]
+pub fn get_emitter_address(program_id: String) -> Vec<u8> {
+    let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
+    let emitter = P2WEmitter::key(None, &program_id);
+
+    emitter.to_bytes().to_vec()
+}
+
+#[wasm_bindgen]
+pub fn parse_attestation(bytes: Vec<u8>) -> JsValue {
+    let a = PriceAttestation::deserialize(bytes.as_slice()).unwrap();
+
+    JsValue::from_serde(&a).unwrap()
+}
+
+#[wasm_bindgen]
+pub fn parse_batch_attestation(bytes: Vec<u8>) -> JsValue {
+    let a = BatchPriceAttestation::deserialize(bytes.as_slice()).unwrap();
+
+    JsValue::from_serde(&a).unwrap()
+}