@reflectmoney/oracle.ts 1.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,7 +25,7 @@ yarn add @reflectmoney/oracle.ts
25
25
  ### Initialize Doppler
26
26
 
27
27
  ```typescript
28
- import { Doppler, PriceFeedSerializer } from "@reflectmoney/oracle.ts";
28
+ import { Doppler, U8Array8Serializer, createPricePayload } from "@reflectmoney/oracle.ts";
29
29
  import { Connection, Keypair } from "@solana/web3.js";
30
30
 
31
31
  const connection = new Connection("https://api.mainnet-beta.solana.com");
@@ -41,26 +41,39 @@ import { PublicKey } from "@solana/web3.js";
41
41
 
42
42
  const oraclePublicKey = new PublicKey("ORACLE_ADDRESS");
43
43
 
44
+ // Create a price payload (8 bytes representing a u64 value)
45
+ const pricePayload = createPricePayload(BigInt(1_000_000)); // 1 USDC
46
+
44
47
  await doppler.updateOracle(
45
48
  oraclePublicKey,
46
49
  {
47
- payload: { price: BigInt(Math.pow(10, 6)) },
48
- sequence: BigInt(Date.now())
50
+ slot: BigInt(Date.now()),
51
+ payload: pricePayload,
49
52
  },
50
- new PriceFeedSerializer(),
53
+ new U8Array8Serializer(),
51
54
  );
52
55
  ```
53
56
 
54
57
  ### Fetch Oracle Data
55
58
 
56
59
  ```typescript
60
+ import { readPriceFromPayload } from "@reflectmoney/oracle.ts";
61
+
57
62
  const oracleData = await doppler.fetchOracle(
58
63
  oraclePublicKey,
59
- new PriceFeedSerializer(),
64
+ new U8Array8Serializer(),
60
65
  );
61
66
 
62
- console.log(oracleData);
63
- // { sequence: 1, payload: { price: 1000000n } }
67
+ if (oracleData) {
68
+ console.log("Slot:", oracleData.slot);
69
+
70
+ // Extract price from the 8-byte payload
71
+ const price = readPriceFromPayload(oracleData.payload);
72
+ console.log("Price:", price);
73
+ }
74
+ // Output:
75
+ // Slot: 1728662400000n
76
+ // Price: 1000000n
64
77
  ```
65
78
 
66
79
  ### Create an Oracle Account
@@ -68,10 +81,10 @@ console.log(oracleData);
68
81
  ```typescript
69
82
  const oracleAccount = await doppler.createOracleAccount(
70
83
  "my-oracle-seed",
71
- new PriceFeedSerializer(),
84
+ new U8Array8Serializer(),
72
85
  {
73
- payload: { price: BigInt(Math.pow(10, 6)) },
74
- sequence: 0n
86
+ slot: 0n,
87
+ payload: createPricePayload(BigInt(1_000_000)),
75
88
  }
76
89
  );
77
90
  ```
package/dist/index.d.ts CHANGED
@@ -3,10 +3,10 @@ import { Buffer } from 'buffer';
3
3
  export declare const DOPPLER_PROGRAM_ID: PublicKey;
4
4
  export declare const ADMIN_PUBKEY: PublicKey;
5
5
  /**
6
- * Generic Oracle data structure
6
+ * Generic Oracle data structure matching Rust implementation
7
7
  */
8
8
  export interface Oracle<T> {
9
- sequence: bigint;
9
+ slot: bigint;
10
10
  payload: T;
11
11
  }
12
12
  /**
@@ -18,27 +18,22 @@ export interface PayloadSerializer<T> {
18
18
  size(): number;
19
19
  }
20
20
  /**
21
- * Built-in serializer for u64 payloads (price feeds)
21
+ * Built-in serializer for [u8; 8] payloads (used for price feeds)
22
+ * The payload is simply 8 bytes representing data in little-endian format
22
23
  */
23
- export declare class U64Serializer implements PayloadSerializer<bigint> {
24
- serialize(payload: bigint): Buffer;
25
- deserialize(buffer: Buffer): bigint;
24
+ export declare class U8Array8Serializer implements PayloadSerializer<Buffer> {
25
+ serialize(payload: Buffer): Buffer;
26
+ deserialize(buffer: Buffer): Buffer;
26
27
  size(): number;
27
28
  }
28
29
  /**
29
- * Price Feed structure matching the Rust implementation
30
+ * Helper function to create a [u8; 8] payload from a bigint price value
30
31
  */
31
- export interface PriceFeed {
32
- price: bigint;
33
- }
32
+ export declare function createPricePayload(price: bigint): Buffer;
34
33
  /**
35
- * Serializer for PriceFeed payloads
34
+ * Helper function to read a price value from a [u8; 8] payload
36
35
  */
37
- export declare class PriceFeedSerializer implements PayloadSerializer<PriceFeed> {
38
- serialize(payload: PriceFeed): Buffer;
39
- deserialize(buffer: Buffer): PriceFeed;
40
- size(): number;
41
- }
36
+ export declare function readPriceFromPayload(payload: Buffer): bigint;
42
37
  /**
43
38
  * Transaction builder for Doppler oracle updates
44
39
  */
@@ -52,7 +47,7 @@ export declare class TransactionBuilder {
52
47
  /**
53
48
  * Add an oracle update instruction to the transaction
54
49
  */
55
- addOracleUpdate<T>(oraclePubkey: PublicKey, oracle: Oracle<T>, serializer: PayloadSerializer<T>): this;
50
+ addOracleUpdate<T>(oraclePubkey: PublicKey, payload: T, serializer: PayloadSerializer<T>): this;
56
51
  /**
57
52
  * Set the compute unit price in micro-lamports
58
53
  */
@@ -62,7 +57,6 @@ export declare class TransactionBuilder {
62
57
  */
63
58
  build(recentBlockhash: string): Transaction;
64
59
  private createUpdateInstruction;
65
- private serializeOracle;
66
60
  }
67
61
  /**
68
62
  * Main Doppler class for interacting with oracle accounts
@@ -86,17 +80,17 @@ export declare class Doppler {
86
80
  /**
87
81
  * Create an oracle account with a seed
88
82
  */
89
- createOracleAccount<T>(seed: string, serializer: PayloadSerializer<T>, initialOracle: Oracle<T>): Promise<PublicKey>;
83
+ createOracleAccount<T>(seed: string, serializer: PayloadSerializer<T>): Promise<PublicKey>;
90
84
  /**
91
85
  * Update a single oracle account
92
86
  */
93
- updateOracle<T>(oraclePubkey: PublicKey, oracle: Oracle<T>, serializer: PayloadSerializer<T>, unitPrice?: bigint): Promise<string>;
87
+ updateOracle<T>(oraclePubkey: PublicKey, payload: T, serializer: PayloadSerializer<T>, unitPrice?: bigint): Promise<string>;
94
88
  /**
95
89
  * Update multiple oracle accounts in a single transaction
96
90
  */
97
91
  updateMultipleOracles<T>(updates: Array<{
98
92
  oraclePubkey: PublicKey;
99
- oracle: Oracle<T>;
93
+ payload: T;
100
94
  serializer: PayloadSerializer<T>;
101
95
  }>, unitPrice?: bigint): Promise<string>;
102
96
  /**
package/dist/index.js CHANGED
@@ -9,7 +9,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.Doppler = exports.TransactionBuilder = exports.PriceFeedSerializer = exports.U64Serializer = exports.ADMIN_PUBKEY = exports.DOPPLER_PROGRAM_ID = void 0;
12
+ exports.Doppler = exports.TransactionBuilder = exports.U8Array8Serializer = exports.ADMIN_PUBKEY = exports.DOPPLER_PROGRAM_ID = void 0;
13
+ exports.createPricePayload = createPricePayload;
14
+ exports.readPriceFromPayload = readPriceFromPayload;
13
15
  const web3_js_1 = require("@solana/web3.js");
14
16
  const buffer_1 = require("buffer");
15
17
  const compute_budget_1 = require("@solana-program/compute-budget");
@@ -28,41 +30,44 @@ const COMPUTE_BUDGET_DATA_LIMIT_SIZE = 5;
28
30
  const COMPUTE_BUDGET_PROGRAM_SIZE = 22;
29
31
  const ORACLE_PROGRAM_SIZE = 36;
30
32
  /**
31
- * Built-in serializer for u64 payloads (price feeds)
33
+ * Built-in serializer for [u8; 8] payloads (used for price feeds)
34
+ * The payload is simply 8 bytes representing data in little-endian format
32
35
  */
33
- class U64Serializer {
36
+ class U8Array8Serializer {
34
37
  serialize(payload) {
35
- const buf = buffer_1.Buffer.alloc(8);
36
- buf.writeBigUInt64LE(payload);
37
- return buf;
38
+ if (payload.length !== 8) {
39
+ throw new Error('Payload must be exactly 8 bytes');
40
+ }
41
+ return payload;
38
42
  }
39
43
  deserialize(buffer) {
40
- return buffer.readBigUInt64LE(0);
44
+ if (buffer.length < 8) {
45
+ throw new Error('Buffer must be at least 8 bytes');
46
+ }
47
+ return buffer.subarray(0, 8);
41
48
  }
42
49
  size() {
43
50
  return 8;
44
51
  }
45
52
  }
46
- exports.U64Serializer = U64Serializer;
53
+ exports.U8Array8Serializer = U8Array8Serializer;
47
54
  /**
48
- * Serializer for PriceFeed payloads
55
+ * Helper function to create a [u8; 8] payload from a bigint price value
49
56
  */
50
- class PriceFeedSerializer {
51
- serialize(payload) {
52
- const buf = buffer_1.Buffer.alloc(8);
53
- buf.writeBigUInt64LE(payload.price);
54
- return buf;
55
- }
56
- deserialize(buffer) {
57
- return {
58
- price: buffer.readBigUInt64LE(0),
59
- };
60
- }
61
- size() {
62
- return 8;
57
+ function createPricePayload(price) {
58
+ const buf = buffer_1.Buffer.alloc(8);
59
+ buf.writeBigUInt64LE(price);
60
+ return buf;
61
+ }
62
+ /**
63
+ * Helper function to read a price value from a [u8; 8] payload
64
+ */
65
+ function readPriceFromPayload(payload) {
66
+ if (payload.length < 8) {
67
+ throw new Error('Payload must be at least 8 bytes');
63
68
  }
69
+ return payload.readBigUInt64LE(0);
64
70
  }
65
- exports.PriceFeedSerializer = PriceFeedSerializer;
66
71
  /**
67
72
  * Transaction builder for Doppler oracle updates
68
73
  */
@@ -80,10 +85,10 @@ class TransactionBuilder {
80
85
  /**
81
86
  * Add an oracle update instruction to the transaction
82
87
  */
83
- addOracleUpdate(oraclePubkey, oracle, serializer) {
84
- const instruction = this.createUpdateInstruction(oraclePubkey, oracle, serializer);
88
+ addOracleUpdate(oraclePubkey, payload, serializer) {
89
+ const instruction = this.createUpdateInstruction(oraclePubkey, payload, serializer);
85
90
  const payloadSize = serializer.size();
86
- const oracleSize = 8 + payloadSize; // sequence + payload
91
+ const oracleSize = 8 + payloadSize; // slot + payload
87
92
  this.computeUnits +=
88
93
  SEQUENCE_CHECK_CU +
89
94
  ADMIN_VERIFICATION_CU +
@@ -134,8 +139,8 @@ class TransactionBuilder {
134
139
  transaction.sign(this.admin);
135
140
  return transaction;
136
141
  }
137
- createUpdateInstruction(oraclePubkey, oracle, serializer) {
138
- const data = this.serializeOracle(oracle, serializer);
142
+ createUpdateInstruction(oraclePubkey, payload, serializer) {
143
+ const data = serializer.serialize(payload);
139
144
  return new web3_js_1.TransactionInstruction({
140
145
  programId: exports.DOPPLER_PROGRAM_ID,
141
146
  keys: [
@@ -149,16 +154,15 @@ class TransactionBuilder {
149
154
  isSigner: false,
150
155
  isWritable: true,
151
156
  },
157
+ {
158
+ pubkey: web3_js_1.SYSVAR_CLOCK_PUBKEY,
159
+ isSigner: false,
160
+ isWritable: false,
161
+ },
152
162
  ],
153
163
  data,
154
164
  });
155
165
  }
156
- serializeOracle(oracle, serializer) {
157
- const sequenceBuffer = buffer_1.Buffer.alloc(8);
158
- sequenceBuffer.writeBigUInt64LE(oracle.sequence);
159
- const payloadBuffer = serializer.serialize(oracle.payload);
160
- return buffer_1.Buffer.concat([sequenceBuffer, payloadBuffer]);
161
- }
162
166
  }
163
167
  exports.TransactionBuilder = TransactionBuilder;
164
168
  /**
@@ -201,15 +205,15 @@ class Doppler {
201
205
  if (data.length < expectedSize) {
202
206
  throw new Error(`Invalid oracle data size. Expected at least ${expectedSize}, got ${data.length}`);
203
207
  }
204
- const sequence = data.readBigUInt64LE(0);
208
+ const slot = data.readBigUInt64LE(0);
205
209
  const payloadBuffer = data.subarray(8, 8 + serializer.size());
206
210
  const payload = serializer.deserialize(payloadBuffer);
207
- return { sequence, payload };
211
+ return { slot, payload };
208
212
  }
209
213
  /**
210
214
  * Create an oracle account with a seed
211
215
  */
212
- createOracleAccount(seed, serializer, initialOracle) {
216
+ createOracleAccount(seed, serializer) {
213
217
  return __awaiter(this, void 0, void 0, function* () {
214
218
  const oracleSize = 8 + serializer.size();
215
219
  const lamports = yield this.connection.getMinimumBalanceForRentExemption(oracleSize);
@@ -237,10 +241,10 @@ class Doppler {
237
241
  /**
238
242
  * Update a single oracle account
239
243
  */
240
- updateOracle(oraclePubkey, oracle, serializer, unitPrice) {
244
+ updateOracle(oraclePubkey, payload, serializer, unitPrice) {
241
245
  return __awaiter(this, void 0, void 0, function* () {
242
246
  const recentBlockhash = yield this.connection.getLatestBlockhash();
243
- let builder = this.createTransactionBuilder().addOracleUpdate(oraclePubkey, oracle, serializer);
247
+ let builder = this.createTransactionBuilder().addOracleUpdate(oraclePubkey, payload, serializer);
244
248
  if (unitPrice !== undefined) {
245
249
  builder = builder.withUnitPrice(unitPrice);
246
250
  }
@@ -257,7 +261,7 @@ class Doppler {
257
261
  const recentBlockhash = yield this.connection.getLatestBlockhash();
258
262
  let builder = this.createTransactionBuilder();
259
263
  for (const update of updates) {
260
- builder = builder.addOracleUpdate(update.oraclePubkey, update.oracle, update.serializer);
264
+ builder = builder.addOracleUpdate(update.oraclePubkey, update.payload, update.serializer);
261
265
  }
262
266
  if (unitPrice !== undefined) {
263
267
  builder = builder.withUnitPrice(unitPrice);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reflectmoney/oracle.ts",
3
- "version": "1.0.1",
3
+ "version": "2.1.0",
4
4
  "type": "commonjs",
5
5
  "author": "L0STE, stablecoinjesus @ Palindrome Engineering",
6
6
  "repository": {