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
|
// Deserialize each attestation
|
||||||
for (uint j=0; j < bpa.nAttestations; j++) {
|
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
|
// Header
|
||||||
bpa.attestations[j].header.magic = encoded.toUint32(index);
|
bpa.attestations[j].header.magic = encoded.toUint32(index + attestationIndex);
|
||||||
index += 4;
|
attestationIndex += 4;
|
||||||
require(bpa.attestations[j].header.magic == 0x50325748, "invalid magic value");
|
require(bpa.attestations[j].header.magic == 0x50325748, "invalid magic value");
|
||||||
|
|
||||||
bpa.attestations[j].header.version = encoded.toUint16(index);
|
bpa.attestations[j].header.version = encoded.toUint16(index + attestationIndex);
|
||||||
index += 2;
|
attestationIndex += 2;
|
||||||
require(bpa.attestations[j].header.version == 2, "invalid version");
|
require(bpa.attestations[j].header.version == 2, "invalid version");
|
||||||
|
|
||||||
bpa.attestations[j].header.payloadId = encoded.toUint8(index);
|
bpa.attestations[j].header.payloadId = encoded.toUint8(index + attestationIndex);
|
||||||
index += 1;
|
attestationIndex += 1;
|
||||||
// Payload ID of 1 required for individual attestation
|
// Payload ID of 1 required for individual attestation
|
||||||
require(bpa.attestations[j].header.payloadId == 1, "invalid payload ID");
|
require(bpa.attestations[j].header.payloadId == 1, "invalid payload ID");
|
||||||
|
|
||||||
// Attestation
|
// Attestation
|
||||||
bpa.attestations[j].productId = encoded.toBytes32(index);
|
bpa.attestations[j].productId = encoded.toBytes32(index + attestationIndex);
|
||||||
index += 32;
|
attestationIndex += 32;
|
||||||
|
|
||||||
bpa.attestations[j].priceId = encoded.toBytes32(index);
|
bpa.attestations[j].priceId = encoded.toBytes32(index + attestationIndex);
|
||||||
index += 32;
|
attestationIndex += 32;
|
||||||
bpa.attestations[j].priceType = encoded.toUint8(index);
|
bpa.attestations[j].priceType = encoded.toUint8(index + attestationIndex);
|
||||||
index += 1;
|
attestationIndex += 1;
|
||||||
|
|
||||||
bpa.attestations[j].price = int64(encoded.toUint64(index));
|
bpa.attestations[j].price = int64(encoded.toUint64(index + attestationIndex));
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
|
|
||||||
bpa.attestations[j].exponent = int32(encoded.toUint32(index));
|
bpa.attestations[j].exponent = int32(encoded.toUint32(index + attestationIndex));
|
||||||
index += 4;
|
attestationIndex += 4;
|
||||||
|
|
||||||
bpa.attestations[j].emaPrice.value = int64(encoded.toUint64(index));
|
bpa.attestations[j].emaPrice.value = int64(encoded.toUint64(index + attestationIndex));
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
bpa.attestations[j].emaPrice.numerator = int64(encoded.toUint64(index));
|
bpa.attestations[j].emaPrice.numerator = int64(encoded.toUint64(index + attestationIndex));
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
bpa.attestations[j].emaPrice.denominator = int64(encoded.toUint64(index));
|
bpa.attestations[j].emaPrice.denominator = int64(encoded.toUint64(index + attestationIndex));
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
|
|
||||||
bpa.attestations[j].emaConf.value = int64(encoded.toUint64(index));
|
bpa.attestations[j].emaConf.value = int64(encoded.toUint64(index + attestationIndex));
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
bpa.attestations[j].emaConf.numerator = int64(encoded.toUint64(index));
|
bpa.attestations[j].emaConf.numerator = int64(encoded.toUint64(index + attestationIndex));
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
bpa.attestations[j].emaConf.denominator = int64(encoded.toUint64(index));
|
bpa.attestations[j].emaConf.denominator = int64(encoded.toUint64(index + attestationIndex));
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
|
|
||||||
bpa.attestations[j].confidenceInterval = encoded.toUint64(index);
|
bpa.attestations[j].confidenceInterval = encoded.toUint64(index + attestationIndex);
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
|
|
||||||
bpa.attestations[j].status = encoded.toUint8(index);
|
bpa.attestations[j].status = encoded.toUint8(index + attestationIndex);
|
||||||
index += 1;
|
attestationIndex += 1;
|
||||||
bpa.attestations[j].corpAct = encoded.toUint8(index);
|
bpa.attestations[j].corpAct = encoded.toUint8(index + attestationIndex);
|
||||||
index += 1;
|
attestationIndex += 1;
|
||||||
|
|
||||||
bpa.attestations[j].timestamp = encoded.toUint64(index);
|
bpa.attestations[j].timestamp = encoded.toUint64(index + attestationIndex);
|
||||||
index += 8;
|
attestationIndex += 8;
|
||||||
|
|
||||||
bpa.attestations[j].num_publishers = encoded.toUint32(index);
|
bpa.attestations[j].num_publishers = encoded.toUint32(index + attestationIndex);
|
||||||
index += 4;
|
attestationIndex += 4;
|
||||||
|
|
||||||
bpa.attestations[j].max_num_publishers = encoded.toUint32(index);
|
bpa.attestations[j].max_num_publishers = encoded.toUint32(index + attestationIndex);
|
||||||
index += 4;
|
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;
|
uint64 timestamp;
|
||||||
uint32 num_publishers;
|
uint32 num_publishers;
|
||||||
uint32 max_num_publishers;
|
uint32 max_num_publishers;
|
||||||
|
uint64 publish_time;
|
||||||
|
uint64 prev_publish_time;
|
||||||
|
int64 prev_price;
|
||||||
|
uint64 prev_conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Rational {
|
struct Rational {
|
||||||
|
|
|
@ -123,8 +123,9 @@ contract("Pyth", function () {
|
||||||
// 3rd price = "0xFCFCFC[...]"
|
// 3rd price = "0xFCFCFC[...]"
|
||||||
const RAW_BATCH_TIMESTAMP_REGEX = /DEADBEEFFADEDEED/g;
|
const RAW_BATCH_TIMESTAMP_REGEX = /DEADBEEFFADEDEED/g;
|
||||||
const RAW_BATCH_PRICE_REGEX = /0000002BAD2FEED7/g;
|
const RAW_BATCH_PRICE_REGEX = /0000002BAD2FEED7/g;
|
||||||
|
const RAW_PRICE_ATTESTATION_SIZE = 190;
|
||||||
const RAW_BATCH_ATTESTATION_COUNT = 10;
|
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
|
// Takes an unsigned 64-bit integer, converts it to hex with 0-padding
|
||||||
function u64ToHex(timestamp) {
|
function u64ToHex(timestamp) {
|
||||||
|
@ -156,7 +157,7 @@ contract("Pyth", function () {
|
||||||
assert.equal(parsed.header.payloadId, 2);
|
assert.equal(parsed.header.payloadId, 2);
|
||||||
|
|
||||||
assert.equal(parsed.nAttestations, RAW_BATCH_ATTESTATION_COUNT);
|
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);
|
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].timestamp, timestamp);
|
||||||
assert.equal(parsed.attestations[i].num_publishers, 123212);
|
assert.equal(parsed.attestations[i].num_publishers, 123212);
|
||||||
assert.equal(parsed.attestations[i].max_num_publishers, 321232);
|
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`);
|
console.debug(`attestation ${i + 1}/${parsed.attestations.length} parsed OK`);
|
||||||
}
|
}
|
||||||
|
@ -265,7 +270,7 @@ contract("Pyth", function () {
|
||||||
|
|
||||||
it("should show stale cached prices as unknown", async function() {
|
it("should show stale cached prices as unknown", async function() {
|
||||||
let smallestTimestamp = 1;
|
let smallestTimestamp = 1;
|
||||||
let rawBatch = generateRawBatchAttestation(smallestTimestamp, 1337);
|
let rawBatch = generateRawBatchAttestation(smallestTimestamp, 1337);
|
||||||
await attest(this.pythProxy, rawBatch);
|
await attest(this.pythProxy, rawBatch);
|
||||||
|
|
||||||
for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) {
|
for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) {
|
||||||
|
@ -277,7 +282,7 @@ contract("Pyth", function () {
|
||||||
|
|
||||||
it("should show cached prices too far into the future as unknown", async function() {
|
it("should show cached prices too far into the future as unknown", async function() {
|
||||||
let largestTimestamp = 4294967295;
|
let largestTimestamp = 4294967295;
|
||||||
let rawBatch = generateRawBatchAttestation(largestTimestamp, 1337);
|
let rawBatch = generateRawBatchAttestation(largestTimestamp, 1337);
|
||||||
await attest(this.pythProxy, rawBatch);
|
await attest(this.pythProxy, rawBatch);
|
||||||
|
|
||||||
for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) {
|
for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) {
|
||||||
|
|
|
@ -1378,9 +1378,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyth-sdk"
|
name = "pyth-sdk"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c610102a39fc4bae29a3b5a628ee134d25afb3dca3937692f5e634f1287fe0b4"
|
checksum = "cb06993b8c8ad7f50042e8b6b6ae4ed2a98722495845b12efc9a12f4301b901b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh",
|
"borsh",
|
||||||
"borsh-derive",
|
"borsh-derive",
|
||||||
|
@ -1390,9 +1390,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyth-sdk-solana"
|
name = "pyth-sdk-solana"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1fdc94592a28fa829b0d6fa619392b1a1744048e5b78a74a4ba93cf541eddae"
|
checksum = "b83f33cbdeccc350e021f6b4bc714655aa38352fac80a93b16b1902863aedb62"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh",
|
"borsh",
|
||||||
"borsh-derive",
|
"borsh-derive",
|
||||||
|
|
|
@ -33,7 +33,7 @@ lazy_static = "1.4.0"
|
||||||
bigint = "4"
|
bigint = "4"
|
||||||
p2w-sdk = { path = "../../../third_party/pyth/p2w-sdk/rust" }
|
p2w-sdk = { path = "../../../third_party/pyth/p2w-sdk/rust" }
|
||||||
solana-program = "=1.8.16"
|
solana-program = "=1.8.16"
|
||||||
pyth-sdk = { version = "0.2.0" }
|
pyth-sdk = "0.3.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cosmwasm-vm = { version = "0.16.0", default-features = false }
|
cosmwasm-vm = { version = "0.16.0", default-features = false }
|
||||||
|
|
|
@ -130,6 +130,7 @@ fn process_batch_attestation(
|
||||||
let price_feed = PriceFeed::new(
|
let price_feed = PriceFeed::new(
|
||||||
price_attestation.price_id.to_bytes(),
|
price_attestation.price_id.to_bytes(),
|
||||||
price_attestation.status,
|
price_attestation.status,
|
||||||
|
price_attestation.publish_time,
|
||||||
price_attestation.expo,
|
price_attestation.expo,
|
||||||
price_attestation.max_num_publishers, // max_num_publishers data is currently unavailable
|
price_attestation.max_num_publishers, // max_num_publishers data is currently unavailable
|
||||||
price_attestation.num_publishers, // 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.confidence_interval,
|
||||||
price_attestation.ema_price.val,
|
price_attestation.ema_price.val,
|
||||||
price_attestation.ema_conf.val as u64,
|
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);
|
let attestation_time = Timestamp::from_seconds(price_attestation.timestamp as u64);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1.2
|
# syntax=docker/dockerfile:1.2
|
||||||
# Wormhole-specific setup for pyth
|
# Wormhole-specific setup for pyth
|
||||||
FROM pythfoundation/pyth-client:devnet-v2.10.1
|
FROM pythfoundation/pyth-client:devnet-v2.11.1
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
|
|
|
@ -631,9 +631,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyth-sdk"
|
name = "pyth-sdk"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c610102a39fc4bae29a3b5a628ee134d25afb3dca3937692f5e634f1287fe0b4"
|
checksum = "cb06993b8c8ad7f50042e8b6b6ae4ed2a98722495845b12efc9a12f4301b901b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh",
|
"borsh",
|
||||||
"borsh-derive",
|
"borsh-derive",
|
||||||
|
@ -643,9 +643,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyth-sdk-solana"
|
name = "pyth-sdk-solana"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1fdc94592a28fa829b0d6fa619392b1a1744048e5b78a74a4ba93cf541eddae"
|
checksum = "b83f33cbdeccc350e021f6b4bc714655aa38352fac80a93b16b1902863aedb62"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"borsh",
|
"borsh",
|
||||||
"borsh-derive",
|
"borsh-derive",
|
||||||
|
|
|
@ -15,7 +15,7 @@ wasm = ["wasm-bindgen", "solana"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
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}
|
wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"], optional = true}
|
||||||
solitaire = { path = "../../../../solana/solitaire/program", optional = true }
|
solitaire = { path = "../../../../solana/solitaire/program", optional = true }
|
||||||
solana-program = "1.8.16"
|
solana-program = "1.8.16"
|
||||||
|
|
|
@ -32,7 +32,6 @@ use solana_program::pubkey::Pubkey;
|
||||||
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
|
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
|
||||||
pub mod wasm;
|
pub mod wasm;
|
||||||
|
|
||||||
/// Quality of life type alias for wrapping up boxed errors.
|
|
||||||
pub type ErrBox = Box<dyn std::error::Error>;
|
pub type ErrBox = Box<dyn std::error::Error>;
|
||||||
|
|
||||||
/// Precedes every message implementing the p2w serialization format
|
/// Precedes every message implementing the p2w serialization format
|
||||||
|
@ -73,9 +72,17 @@ pub struct PriceAttestation {
|
||||||
pub confidence_interval: u64,
|
pub confidence_interval: u64,
|
||||||
pub status: PriceStatus,
|
pub status: PriceStatus,
|
||||||
pub corp_act: CorpAction,
|
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 timestamp: UnixTimestamp,
|
||||||
pub num_publishers: u32,
|
pub num_publishers: u32,
|
||||||
pub max_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)]
|
#[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 {
|
impl PriceAttestation {
|
||||||
pub fn from_pyth_price_bytes(
|
pub fn from_pyth_price_bytes(
|
||||||
price_id: Pubkey,
|
price_id: Pubkey,
|
||||||
timestamp: UnixTimestamp,
|
attestation_time: UnixTimestamp,
|
||||||
value: &[u8],
|
value: &[u8],
|
||||||
) -> Result<Self, ErrBox> {
|
) -> Result<Self, ErrBox> {
|
||||||
let price = pyth_sdk_solana::state::load_price_account(value)?;
|
let price = pyth_sdk_solana::state::load_price_account(value)?;
|
||||||
|
@ -252,9 +259,13 @@ impl PriceAttestation {
|
||||||
confidence_interval: price.agg.conf,
|
confidence_interval: price.agg.conf,
|
||||||
status: price.agg.status,
|
status: price.agg.status,
|
||||||
corp_act: price.agg.corp_act,
|
corp_act: price.agg.corp_act,
|
||||||
timestamp: timestamp,
|
timestamp: attestation_time,
|
||||||
num_publishers: price.num_qt,
|
num_publishers: price.num_qt,
|
||||||
max_num_publishers: price.num,
|
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,
|
timestamp,
|
||||||
num_publishers,
|
num_publishers,
|
||||||
max_num_publishers,
|
max_num_publishers,
|
||||||
|
publish_time,
|
||||||
|
prev_publish_time,
|
||||||
|
prev_price,
|
||||||
|
prev_conf
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// magic
|
// magic
|
||||||
|
@ -326,6 +341,18 @@ impl PriceAttestation {
|
||||||
// max_num_publishers
|
// max_num_publishers
|
||||||
buf.extend_from_slice(&max_num_publishers.to_be_bytes()[..]);
|
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
|
buf
|
||||||
}
|
}
|
||||||
pub fn deserialize(mut bytes: impl Read) -> Result<Self, ErrBox> {
|
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())?;
|
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 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 {
|
Ok(Self {
|
||||||
product_id,
|
product_id,
|
||||||
price_id,
|
price_id,
|
||||||
|
@ -446,7 +489,11 @@ impl PriceAttestation {
|
||||||
corp_act,
|
corp_act,
|
||||||
timestamp,
|
timestamp,
|
||||||
num_publishers,
|
num_publishers,
|
||||||
max_num_publishers,
|
max_num_publishers,
|
||||||
|
publish_time,
|
||||||
|
prev_publish_time,
|
||||||
|
prev_price,
|
||||||
|
prev_conf,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,7 +534,11 @@ mod tests {
|
||||||
corp_act: CorpAction::NoCorpAct,
|
corp_act: CorpAction::NoCorpAct,
|
||||||
timestamp: (0xdeadbeeffadedeedu64) as i64,
|
timestamp: (0xdeadbeeffadedeedu64) as i64,
|
||||||
num_publishers: 123212u32,
|
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