pyth2wormhole: Add compatible metadata, handle EVM fwd-compat (#165)
* pyth2wormhole: Add compatible metadata, handle EVM fwd-compat commit-id:d92b42b5 * EVM unit tests: test the non-breaking format change fields commit-id:3a26e554
This commit is contained in:
parent
ded0fb37bd
commit
b41708e863
|
@ -106,65 +106,87 @@ contract Pyth is PythGetters, PythSetters, AbstractPyth {
|
|||
|
||||
// Deserialize each attestation
|
||||
for (uint j=0; j < bpa.nAttestations; j++) {
|
||||
// NOTE: We don't advance the global index immediately.
|
||||
// attestationIndex is an attestation-local offset used
|
||||
// for readability and easier debugging.
|
||||
uint attestationIndex = 0;
|
||||
|
||||
// Header
|
||||
bpa.attestations[j].header.magic = encoded.toUint32(index);
|
||||
index += 4;
|
||||
bpa.attestations[j].header.magic = encoded.toUint32(index + attestationIndex);
|
||||
attestationIndex += 4;
|
||||
require(bpa.attestations[j].header.magic == 0x50325748, "invalid magic value");
|
||||
|
||||
bpa.attestations[j].header.version = encoded.toUint16(index);
|
||||
index += 2;
|
||||
bpa.attestations[j].header.version = encoded.toUint16(index + attestationIndex);
|
||||
attestationIndex += 2;
|
||||
require(bpa.attestations[j].header.version == 2, "invalid version");
|
||||
|
||||
bpa.attestations[j].header.payloadId = encoded.toUint8(index);
|
||||
index += 1;
|
||||
bpa.attestations[j].header.payloadId = encoded.toUint8(index + attestationIndex);
|
||||
attestationIndex += 1;
|
||||
// Payload ID of 1 required for individual attestation
|
||||
require(bpa.attestations[j].header.payloadId == 1, "invalid payload ID");
|
||||
|
||||
// Attestation
|
||||
bpa.attestations[j].productId = encoded.toBytes32(index);
|
||||
index += 32;
|
||||
bpa.attestations[j].productId = encoded.toBytes32(index + attestationIndex);
|
||||
attestationIndex += 32;
|
||||
|
||||
bpa.attestations[j].priceId = encoded.toBytes32(index);
|
||||
index += 32;
|
||||
bpa.attestations[j].priceType = encoded.toUint8(index);
|
||||
index += 1;
|
||||
bpa.attestations[j].priceId = encoded.toBytes32(index + attestationIndex);
|
||||
attestationIndex += 32;
|
||||
bpa.attestations[j].priceType = encoded.toUint8(index + attestationIndex);
|
||||
attestationIndex += 1;
|
||||
|
||||
bpa.attestations[j].price = int64(encoded.toUint64(index));
|
||||
index += 8;
|
||||
bpa.attestations[j].price = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].exponent = int32(encoded.toUint32(index));
|
||||
index += 4;
|
||||
bpa.attestations[j].exponent = int32(encoded.toUint32(index + attestationIndex));
|
||||
attestationIndex += 4;
|
||||
|
||||
bpa.attestations[j].emaPrice.value = int64(encoded.toUint64(index));
|
||||
index += 8;
|
||||
bpa.attestations[j].emaPrice.numerator = int64(encoded.toUint64(index));
|
||||
index += 8;
|
||||
bpa.attestations[j].emaPrice.denominator = int64(encoded.toUint64(index));
|
||||
index += 8;
|
||||
bpa.attestations[j].emaPrice.value = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
bpa.attestations[j].emaPrice.numerator = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
bpa.attestations[j].emaPrice.denominator = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].emaConf.value = int64(encoded.toUint64(index));
|
||||
index += 8;
|
||||
bpa.attestations[j].emaConf.numerator = int64(encoded.toUint64(index));
|
||||
index += 8;
|
||||
bpa.attestations[j].emaConf.denominator = int64(encoded.toUint64(index));
|
||||
index += 8;
|
||||
bpa.attestations[j].emaConf.value = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
bpa.attestations[j].emaConf.numerator = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
bpa.attestations[j].emaConf.denominator = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].confidenceInterval = encoded.toUint64(index);
|
||||
index += 8;
|
||||
bpa.attestations[j].confidenceInterval = encoded.toUint64(index + attestationIndex);
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].status = encoded.toUint8(index);
|
||||
index += 1;
|
||||
bpa.attestations[j].corpAct = encoded.toUint8(index);
|
||||
index += 1;
|
||||
bpa.attestations[j].status = encoded.toUint8(index + attestationIndex);
|
||||
attestationIndex += 1;
|
||||
bpa.attestations[j].corpAct = encoded.toUint8(index + attestationIndex);
|
||||
attestationIndex += 1;
|
||||
|
||||
bpa.attestations[j].timestamp = encoded.toUint64(index);
|
||||
index += 8;
|
||||
bpa.attestations[j].timestamp = encoded.toUint64(index + attestationIndex);
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].num_publishers = encoded.toUint32(index);
|
||||
index += 4;
|
||||
bpa.attestations[j].num_publishers = encoded.toUint32(index + attestationIndex);
|
||||
attestationIndex += 4;
|
||||
|
||||
bpa.attestations[j].max_num_publishers = encoded.toUint32(index);
|
||||
index += 4;
|
||||
bpa.attestations[j].max_num_publishers = encoded.toUint32(index + attestationIndex);
|
||||
attestationIndex += 4;
|
||||
|
||||
bpa.attestations[j].publish_time = encoded.toUint64(index + attestationIndex);
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].prev_publish_time = encoded.toUint64(index + attestationIndex);
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].prev_price = int64(encoded.toUint64(index + attestationIndex));
|
||||
attestationIndex += 8;
|
||||
|
||||
bpa.attestations[j].prev_conf = encoded.toUint64(index + attestationIndex);
|
||||
attestationIndex += 8;
|
||||
|
||||
require(attestationIndex <= bpa.attestationSize, "INTERNAL: Consumed more than `attestationSize` bytes");
|
||||
|
||||
// Respect specified attestation size for forward-compat
|
||||
index += bpa.attestationSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ contract PythInternalStructs {
|
|||
uint64 timestamp;
|
||||
uint32 num_publishers;
|
||||
uint32 max_num_publishers;
|
||||
uint64 publish_time;
|
||||
uint64 prev_publish_time;
|
||||
int64 prev_price;
|
||||
uint64 prev_conf;
|
||||
}
|
||||
|
||||
struct Rational {
|
||||
|
|
|
@ -123,8 +123,9 @@ contract("Pyth", function () {
|
|||
// 3rd price = "0xFCFCFC[...]"
|
||||
const RAW_BATCH_TIMESTAMP_REGEX = /DEADBEEFFADEDEED/g;
|
||||
const RAW_BATCH_PRICE_REGEX = /0000002BAD2FEED7/g;
|
||||
const RAW_PRICE_ATTESTATION_SIZE = 190;
|
||||
const RAW_BATCH_ATTESTATION_COUNT = 10;
|
||||
const rawBatchPriceAttestation = "0x" + "50325748000202000A009E503257480002010101010101010101010101010101010101010101010101010101010101010101FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010202020202020202020202020202020202020202020202020202020202020202FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010303030303030303030303030303030303030303030303030303030303030303FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010404040404040404040404040404040404040404040404040404040404040404FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010505050505050505050505050505050505050505050505050505050505050505FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010606060606060606060606060606060606060606060606060606060606060606F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010707070707070707070707070707070707070707070707070707070707070707F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010808080808080808080808080808080808080808080808080808080808080808F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010909090909090909090909090909090909090909090909090909090909090909F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0503257480002010A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AF5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D0";
|
||||
const rawBatchPriceAttestation = "0x" + "50325748000202000A00BE503257480002010101010101010101010101010101010101010101010101010101010101010101FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010202020202020202020202020202020202020202020202020202020202020202FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010303030303030303030303030303030303030303030303030303030303030303FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010404040404040404040404040404040404040404040404040404040404040404FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010505050505050505050505050505050505050505050505050505050505050505FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010606060606060606060606060606060606060606060606060606060606060606F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010707070707070707070707070707070707070707070707070707070707070707F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010808080808080808080808080808080808080808080808080808080808080808F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010909090909090909090909090909090909090909090909090909090909090909F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF503257480002010A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AF5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5010000002BAD2FEED7FFFFFFFDFFFFFFFFFFFFFFD6000000000000000F0000000000000025000000000000002A000000000000045700000000000008AE00000000000000650100DEADBEEFFADEDEED0001E14C0004E6D000000000DEADBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF";
|
||||
|
||||
// Takes an unsigned 64-bit integer, converts it to hex with 0-padding
|
||||
function u64ToHex(timestamp) {
|
||||
|
@ -156,7 +157,7 @@ contract("Pyth", function () {
|
|||
assert.equal(parsed.header.payloadId, 2);
|
||||
|
||||
assert.equal(parsed.nAttestations, RAW_BATCH_ATTESTATION_COUNT);
|
||||
assert.equal(parsed.attestationSize, 158);
|
||||
assert.equal(parsed.attestationSize, RAW_PRICE_ATTESTATION_SIZE);
|
||||
|
||||
assert.equal(parsed.attestations.length, parsed.nAttestations);
|
||||
|
||||
|
@ -186,6 +187,10 @@ contract("Pyth", function () {
|
|||
assert.equal(parsed.attestations[i].timestamp, timestamp);
|
||||
assert.equal(parsed.attestations[i].num_publishers, 123212);
|
||||
assert.equal(parsed.attestations[i].max_num_publishers, 321232);
|
||||
assert.equal(parsed.attestations[i].publish_time, 0xdeadbeef);
|
||||
assert.equal(parsed.attestations[i].prev_publish_time, 0xdeadbabe);
|
||||
assert.equal(parsed.attestations[i].prev_price, 0xdeadfacebeef);
|
||||
assert.equal(parsed.attestations[i].prev_conf, 0xbadbadbeef);
|
||||
|
||||
console.debug(`attestation ${i + 1}/${parsed.attestations.length} parsed OK`);
|
||||
}
|
||||
|
|
|
@ -1378,9 +1378,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pyth-sdk"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c610102a39fc4bae29a3b5a628ee134d25afb3dca3937692f5e634f1287fe0b4"
|
||||
checksum = "cb06993b8c8ad7f50042e8b6b6ae4ed2a98722495845b12efc9a12f4301b901b"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"borsh-derive",
|
||||
|
@ -1390,9 +1390,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pyth-sdk-solana"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1fdc94592a28fa829b0d6fa619392b1a1744048e5b78a74a4ba93cf541eddae"
|
||||
checksum = "b83f33cbdeccc350e021f6b4bc714655aa38352fac80a93b16b1902863aedb62"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"borsh-derive",
|
||||
|
|
|
@ -33,7 +33,7 @@ lazy_static = "1.4.0"
|
|||
bigint = "4"
|
||||
p2w-sdk = { path = "../../../third_party/pyth/p2w-sdk/rust" }
|
||||
solana-program = "=1.8.16"
|
||||
pyth-sdk = { version = "0.2.0" }
|
||||
pyth-sdk = "0.3.0"
|
||||
|
||||
[dev-dependencies]
|
||||
cosmwasm-vm = { version = "0.16.0", default-features = false }
|
||||
|
|
|
@ -130,6 +130,7 @@ fn process_batch_attestation(
|
|||
let price_feed = PriceFeed::new(
|
||||
price_attestation.price_id.to_bytes(),
|
||||
price_attestation.status,
|
||||
price_attestation.publish_time,
|
||||
price_attestation.expo,
|
||||
price_attestation.max_num_publishers, // max_num_publishers data is currently unavailable
|
||||
price_attestation.num_publishers, // num_publishers data is currently unavailable
|
||||
|
@ -138,6 +139,9 @@ fn process_batch_attestation(
|
|||
price_attestation.confidence_interval,
|
||||
price_attestation.ema_price.val,
|
||||
price_attestation.ema_conf.val as u64,
|
||||
price_attestation.prev_price,
|
||||
price_attestation.prev_conf,
|
||||
price_attestation.prev_publish_time,
|
||||
);
|
||||
|
||||
let attestation_time = Timestamp::from_seconds(price_attestation.timestamp as u64);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# syntax=docker/dockerfile:1.2
|
||||
# Wormhole-specific setup for pyth
|
||||
FROM pythfoundation/pyth-client:devnet-v2.10.1
|
||||
FROM pythfoundation/pyth-client:devnet-v2.11.1
|
||||
|
||||
USER root
|
||||
|
||||
|
|
|
@ -631,9 +631,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pyth-sdk"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c610102a39fc4bae29a3b5a628ee134d25afb3dca3937692f5e634f1287fe0b4"
|
||||
checksum = "cb06993b8c8ad7f50042e8b6b6ae4ed2a98722495845b12efc9a12f4301b901b"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"borsh-derive",
|
||||
|
@ -643,9 +643,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pyth-sdk-solana"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1fdc94592a28fa829b0d6fa619392b1a1744048e5b78a74a4ba93cf541eddae"
|
||||
checksum = "b83f33cbdeccc350e021f6b4bc714655aa38352fac80a93b16b1902863aedb62"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"borsh-derive",
|
||||
|
|
|
@ -15,7 +15,7 @@ wasm = ["wasm-bindgen", "solana"]
|
|||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
pyth-sdk-solana = { version = "0.2.0" }
|
||||
pyth-sdk-solana = "0.3.0"
|
||||
wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"], optional = true}
|
||||
solitaire = { path = "../../../../solana/solitaire/program", optional = true }
|
||||
solana-program = "1.8.16"
|
||||
|
|
|
@ -32,7 +32,6 @@ use solana_program::pubkey::Pubkey;
|
|||
#[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
|
||||
|
@ -73,9 +72,17 @@ pub struct PriceAttestation {
|
|||
pub confidence_interval: u64,
|
||||
pub status: PriceStatus,
|
||||
pub corp_act: CorpAction,
|
||||
// TODO(2022-04-07) format v3: Rename this aptly named timestamp
|
||||
// field to attestation_time (it's a grey area in terms of
|
||||
// compatibility and v3 is due very soon either way)
|
||||
/// NOTE: SOL on-chain time of attestation
|
||||
pub timestamp: UnixTimestamp,
|
||||
pub num_publishers: u32,
|
||||
pub max_num_publishers: u32,
|
||||
pub publish_time: UnixTimestamp,
|
||||
pub prev_publish_time: UnixTimestamp,
|
||||
pub prev_price: i64,
|
||||
pub prev_conf: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -236,7 +243,7 @@ pub fn deserialize_rational(mut bytes: impl Read) -> Result<Rational, ErrBox> {
|
|||
impl PriceAttestation {
|
||||
pub fn from_pyth_price_bytes(
|
||||
price_id: Pubkey,
|
||||
timestamp: UnixTimestamp,
|
||||
attestation_time: UnixTimestamp,
|
||||
value: &[u8],
|
||||
) -> Result<Self, ErrBox> {
|
||||
let price = pyth_sdk_solana::state::load_price_account(value)?;
|
||||
|
@ -252,9 +259,13 @@ impl PriceAttestation {
|
|||
confidence_interval: price.agg.conf,
|
||||
status: price.agg.status,
|
||||
corp_act: price.agg.corp_act,
|
||||
timestamp: timestamp,
|
||||
timestamp: attestation_time,
|
||||
num_publishers: price.num_qt,
|
||||
max_num_publishers: price.num,
|
||||
publish_time: price.timestamp,
|
||||
prev_publish_time: price.prev_timestamp,
|
||||
prev_price: price.prev_price,
|
||||
prev_conf: price.prev_conf,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -276,6 +287,10 @@ impl PriceAttestation {
|
|||
timestamp,
|
||||
num_publishers,
|
||||
max_num_publishers,
|
||||
publish_time,
|
||||
prev_publish_time,
|
||||
prev_price,
|
||||
prev_conf
|
||||
} = self;
|
||||
|
||||
// magic
|
||||
|
@ -326,6 +341,18 @@ impl PriceAttestation {
|
|||
// max_num_publishers
|
||||
buf.extend_from_slice(&max_num_publishers.to_be_bytes()[..]);
|
||||
|
||||
// publish_time
|
||||
buf.extend_from_slice(&publish_time.to_be_bytes()[..]);
|
||||
|
||||
// prev_publish_time
|
||||
buf.extend_from_slice(&prev_publish_time.to_be_bytes()[..]);
|
||||
|
||||
// prev_price
|
||||
buf.extend_from_slice(&prev_price.to_be_bytes()[..]);
|
||||
|
||||
// prev_conf
|
||||
buf.extend_from_slice(&prev_conf.to_be_bytes()[..]);
|
||||
|
||||
buf
|
||||
}
|
||||
pub fn deserialize(mut bytes: impl Read) -> Result<Self, ErrBox> {
|
||||
|
@ -433,6 +460,22 @@ impl PriceAttestation {
|
|||
bytes.read_exact(max_num_publishers_vec.as_mut_slice())?;
|
||||
let max_num_publishers = u32::from_be_bytes(max_num_publishers_vec.as_slice().try_into()?);
|
||||
|
||||
let mut publish_time_vec = vec![0u8; mem::size_of::<UnixTimestamp>()];
|
||||
bytes.read_exact(publish_time_vec.as_mut_slice())?;
|
||||
let publish_time = UnixTimestamp::from_be_bytes(publish_time_vec.as_slice().try_into()?);
|
||||
|
||||
let mut prev_publish_time_vec = vec![0u8; mem::size_of::<UnixTimestamp>()];
|
||||
bytes.read_exact(prev_publish_time_vec.as_mut_slice())?;
|
||||
let prev_publish_time = UnixTimestamp::from_be_bytes(prev_publish_time_vec.as_slice().try_into()?);
|
||||
|
||||
let mut prev_price_vec = vec![0u8; mem::size_of::<i64>()];
|
||||
bytes.read_exact(prev_price_vec.as_mut_slice())?;
|
||||
let prev_price = i64::from_be_bytes(prev_price_vec.as_slice().try_into()?);
|
||||
|
||||
let mut prev_conf_vec = vec![0u8; mem::size_of::<u64>()];
|
||||
bytes.read_exact(prev_conf_vec.as_mut_slice())?;
|
||||
let prev_conf = u64::from_be_bytes(prev_conf_vec.as_slice().try_into()?);
|
||||
|
||||
Ok(Self {
|
||||
product_id,
|
||||
price_id,
|
||||
|
@ -447,6 +490,10 @@ impl PriceAttestation {
|
|||
timestamp,
|
||||
num_publishers,
|
||||
max_num_publishers,
|
||||
publish_time,
|
||||
prev_publish_time,
|
||||
prev_price,
|
||||
prev_conf,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +534,11 @@ mod tests {
|
|||
corp_act: CorpAction::NoCorpAct,
|
||||
timestamp: (0xdeadbeeffadedeedu64) as i64,
|
||||
num_publishers: 123212u32,
|
||||
max_num_publishers: 321232u32
|
||||
max_num_publishers: 321232u32,
|
||||
publish_time: 0xdeadbeefi64,
|
||||
prev_publish_time: 0xdeadbabei64,
|
||||
prev_price: 0xdeadfacebeefi64,
|
||||
prev_conf: 0xbadbadbeefu64, // I could do this all day -SD
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue