@exponent-labs/chainlink-idl 0.9.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.
@@ -0,0 +1,503 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "name": "store",
4
+ "constants": [
5
+ {
6
+ "name": "HEADER_SIZE",
7
+ "type": {
8
+ "defined": "usize"
9
+ },
10
+ "value": "192"
11
+ }
12
+ ],
13
+ "instructions": [
14
+ {
15
+ "name": "createFeed",
16
+ "accounts": [
17
+ {
18
+ "name": "feed",
19
+ "isMut": true,
20
+ "isSigner": false
21
+ },
22
+ {
23
+ "name": "authority",
24
+ "isMut": false,
25
+ "isSigner": true
26
+ }
27
+ ],
28
+ "args": [
29
+ {
30
+ "name": "description",
31
+ "type": "string"
32
+ },
33
+ {
34
+ "name": "decimals",
35
+ "type": "u8"
36
+ },
37
+ {
38
+ "name": "granularity",
39
+ "type": "u8"
40
+ },
41
+ {
42
+ "name": "liveLength",
43
+ "type": "u32"
44
+ }
45
+ ]
46
+ },
47
+ {
48
+ "name": "closeFeed",
49
+ "accounts": [
50
+ {
51
+ "name": "feed",
52
+ "isMut": true,
53
+ "isSigner": false
54
+ },
55
+ {
56
+ "name": "owner",
57
+ "isMut": false,
58
+ "isSigner": false
59
+ },
60
+ {
61
+ "name": "receiver",
62
+ "isMut": true,
63
+ "isSigner": false
64
+ },
65
+ {
66
+ "name": "authority",
67
+ "isMut": false,
68
+ "isSigner": true
69
+ }
70
+ ],
71
+ "args": []
72
+ },
73
+ {
74
+ "name": "transferFeedOwnership",
75
+ "accounts": [
76
+ {
77
+ "name": "feed",
78
+ "isMut": true,
79
+ "isSigner": false
80
+ },
81
+ {
82
+ "name": "owner",
83
+ "isMut": false,
84
+ "isSigner": false
85
+ },
86
+ {
87
+ "name": "authority",
88
+ "isMut": false,
89
+ "isSigner": true
90
+ }
91
+ ],
92
+ "args": [
93
+ {
94
+ "name": "proposedOwner",
95
+ "type": "publicKey"
96
+ }
97
+ ]
98
+ },
99
+ {
100
+ "name": "acceptFeedOwnership",
101
+ "accounts": [
102
+ {
103
+ "name": "feed",
104
+ "isMut": true,
105
+ "isSigner": false
106
+ },
107
+ {
108
+ "name": "proposedOwner",
109
+ "isMut": false,
110
+ "isSigner": false
111
+ },
112
+ {
113
+ "name": "authority",
114
+ "isMut": false,
115
+ "isSigner": true
116
+ }
117
+ ],
118
+ "args": []
119
+ },
120
+ {
121
+ "name": "setValidatorConfig",
122
+ "accounts": [
123
+ {
124
+ "name": "feed",
125
+ "isMut": true,
126
+ "isSigner": false
127
+ },
128
+ {
129
+ "name": "owner",
130
+ "isMut": false,
131
+ "isSigner": false
132
+ },
133
+ {
134
+ "name": "authority",
135
+ "isMut": false,
136
+ "isSigner": true
137
+ }
138
+ ],
139
+ "args": [
140
+ {
141
+ "name": "flaggingThreshold",
142
+ "type": "u32"
143
+ }
144
+ ]
145
+ },
146
+ {
147
+ "name": "setWriter",
148
+ "accounts": [
149
+ {
150
+ "name": "feed",
151
+ "isMut": true,
152
+ "isSigner": false
153
+ },
154
+ {
155
+ "name": "owner",
156
+ "isMut": false,
157
+ "isSigner": false
158
+ },
159
+ {
160
+ "name": "authority",
161
+ "isMut": false,
162
+ "isSigner": true
163
+ }
164
+ ],
165
+ "args": [
166
+ {
167
+ "name": "writer",
168
+ "type": "publicKey"
169
+ }
170
+ ]
171
+ },
172
+ {
173
+ "name": "lowerFlag",
174
+ "accounts": [
175
+ {
176
+ "name": "feed",
177
+ "isMut": true,
178
+ "isSigner": false
179
+ },
180
+ {
181
+ "name": "owner",
182
+ "isMut": false,
183
+ "isSigner": false
184
+ },
185
+ {
186
+ "name": "authority",
187
+ "isMut": false,
188
+ "isSigner": true
189
+ },
190
+ {
191
+ "name": "accessController",
192
+ "isMut": false,
193
+ "isSigner": false
194
+ }
195
+ ],
196
+ "args": []
197
+ },
198
+ {
199
+ "name": "submit",
200
+ "accounts": [
201
+ {
202
+ "name": "feed",
203
+ "isMut": true,
204
+ "isSigner": false
205
+ },
206
+ {
207
+ "name": "authority",
208
+ "isMut": false,
209
+ "isSigner": true
210
+ }
211
+ ],
212
+ "args": [
213
+ {
214
+ "name": "round",
215
+ "type": {
216
+ "defined": "NewTransmission"
217
+ }
218
+ }
219
+ ]
220
+ },
221
+ {
222
+ "name": "initialize",
223
+ "accounts": [
224
+ {
225
+ "name": "store",
226
+ "isMut": true,
227
+ "isSigner": false
228
+ },
229
+ {
230
+ "name": "owner",
231
+ "isMut": false,
232
+ "isSigner": true
233
+ },
234
+ {
235
+ "name": "loweringAccessController",
236
+ "isMut": false,
237
+ "isSigner": false
238
+ }
239
+ ],
240
+ "args": []
241
+ },
242
+ {
243
+ "name": "transferStoreOwnership",
244
+ "accounts": [
245
+ {
246
+ "name": "store",
247
+ "isMut": true,
248
+ "isSigner": false
249
+ },
250
+ {
251
+ "name": "authority",
252
+ "isMut": false,
253
+ "isSigner": true
254
+ }
255
+ ],
256
+ "args": [
257
+ {
258
+ "name": "proposedOwner",
259
+ "type": "publicKey"
260
+ }
261
+ ]
262
+ },
263
+ {
264
+ "name": "acceptStoreOwnership",
265
+ "accounts": [
266
+ {
267
+ "name": "store",
268
+ "isMut": true,
269
+ "isSigner": false
270
+ },
271
+ {
272
+ "name": "authority",
273
+ "isMut": false,
274
+ "isSigner": true
275
+ }
276
+ ],
277
+ "args": []
278
+ },
279
+ {
280
+ "name": "setLoweringAccessController",
281
+ "accounts": [
282
+ {
283
+ "name": "store",
284
+ "isMut": true,
285
+ "isSigner": false
286
+ },
287
+ {
288
+ "name": "authority",
289
+ "isMut": false,
290
+ "isSigner": true
291
+ },
292
+ {
293
+ "name": "accessController",
294
+ "isMut": false,
295
+ "isSigner": false
296
+ }
297
+ ],
298
+ "args": []
299
+ },
300
+ {
301
+ "name": "query",
302
+ "accounts": [
303
+ {
304
+ "name": "feed",
305
+ "isMut": false,
306
+ "isSigner": false
307
+ }
308
+ ],
309
+ "args": [
310
+ {
311
+ "name": "scope",
312
+ "type": {
313
+ "defined": "Scope"
314
+ }
315
+ }
316
+ ]
317
+ }
318
+ ],
319
+ "accounts": [
320
+ {
321
+ "name": "Store",
322
+ "type": {
323
+ "kind": "struct",
324
+ "fields": [
325
+ {
326
+ "name": "owner",
327
+ "type": "publicKey"
328
+ },
329
+ {
330
+ "name": "proposedOwner",
331
+ "type": "publicKey"
332
+ },
333
+ {
334
+ "name": "loweringAccessController",
335
+ "type": "publicKey"
336
+ }
337
+ ]
338
+ }
339
+ },
340
+ {
341
+ "name": "Transmissions",
342
+ "type": {
343
+ "kind": "struct",
344
+ "fields": [
345
+ {
346
+ "name": "version",
347
+ "type": "u8"
348
+ },
349
+ {
350
+ "name": "state",
351
+ "type": "u8"
352
+ },
353
+ {
354
+ "name": "owner",
355
+ "type": "publicKey"
356
+ },
357
+ {
358
+ "name": "proposedOwner",
359
+ "type": "publicKey"
360
+ },
361
+ {
362
+ "name": "writer",
363
+ "type": "publicKey"
364
+ },
365
+ {
366
+ "name": "description",
367
+ "type": {
368
+ "array": ["u8", 32]
369
+ }
370
+ },
371
+ {
372
+ "name": "decimals",
373
+ "type": "u8"
374
+ },
375
+ {
376
+ "name": "flaggingThreshold",
377
+ "type": "u32"
378
+ },
379
+ {
380
+ "name": "latestRoundId",
381
+ "type": "u32"
382
+ },
383
+ {
384
+ "name": "granularity",
385
+ "type": "u8"
386
+ },
387
+ {
388
+ "name": "liveLength",
389
+ "type": "u32"
390
+ },
391
+ {
392
+ "name": "liveCursor",
393
+ "type": "u32"
394
+ },
395
+ {
396
+ "name": "historicalCursor",
397
+ "type": "u32"
398
+ }
399
+ ]
400
+ }
401
+ }
402
+ ],
403
+ "types": [
404
+ {
405
+ "name": "NewTransmission",
406
+ "type": {
407
+ "kind": "struct",
408
+ "fields": [
409
+ {
410
+ "name": "timestamp",
411
+ "type": "u64"
412
+ },
413
+ {
414
+ "name": "answer",
415
+ "type": "i128"
416
+ }
417
+ ]
418
+ }
419
+ },
420
+ {
421
+ "name": "Round",
422
+ "type": {
423
+ "kind": "struct",
424
+ "fields": [
425
+ {
426
+ "name": "roundId",
427
+ "type": "u32"
428
+ },
429
+ {
430
+ "name": "slot",
431
+ "type": "u64"
432
+ },
433
+ {
434
+ "name": "timestamp",
435
+ "type": "u32"
436
+ },
437
+ {
438
+ "name": "answer",
439
+ "type": "i128"
440
+ }
441
+ ]
442
+ }
443
+ },
444
+ {
445
+ "name": "Scope",
446
+ "type": {
447
+ "kind": "enum",
448
+ "variants": [
449
+ {
450
+ "name": "Version"
451
+ },
452
+ {
453
+ "name": "Decimals"
454
+ },
455
+ {
456
+ "name": "Description"
457
+ },
458
+ {
459
+ "name": "RoundData",
460
+ "fields": [
461
+ {
462
+ "name": "round_id",
463
+ "type": "u32"
464
+ }
465
+ ]
466
+ },
467
+ {
468
+ "name": "LatestRoundData"
469
+ },
470
+ {
471
+ "name": "Aggregator"
472
+ }
473
+ ]
474
+ }
475
+ }
476
+ ],
477
+ "errors": [
478
+ {
479
+ "code": 6000,
480
+ "name": "Unauthorized",
481
+ "msg": "Unauthorized"
482
+ },
483
+ {
484
+ "code": 6001,
485
+ "name": "InvalidInput",
486
+ "msg": "Invalid input"
487
+ },
488
+ {
489
+ "code": 6002,
490
+ "name": "NotFound"
491
+ },
492
+ {
493
+ "code": 6003,
494
+ "name": "InvalidVersion",
495
+ "msg": "Invalid version"
496
+ },
497
+ {
498
+ "code": 6004,
499
+ "name": "InsufficientSize",
500
+ "msg": "Insufficient or invalid feed account size, has to be `8 + HEADER_SIZE + n * size_of::<Transmission>()`"
501
+ }
502
+ ]
503
+ }
@@ -0,0 +1,18 @@
1
+ import { web3 } from "@coral-xyz/anchor";
2
+ export interface Transmissions {
3
+ version: number;
4
+ state: number;
5
+ owner: web3.PublicKey;
6
+ proposedOwner: web3.PublicKey;
7
+ writer: web3.PublicKey;
8
+ description: Uint8Array;
9
+ decimals: number;
10
+ flaggingThreshold: number;
11
+ latestRoundId: number;
12
+ granularity: number;
13
+ liveLength: number;
14
+ liveCursor: number;
15
+ historicalCursor: number;
16
+ }
17
+ export declare const MAX_DESCRIPTION_LEN = 32;
18
+ export declare const transmissionsLayout: import("@solana/buffer-layout").Structure<Transmissions>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transmissionsLayout = exports.MAX_DESCRIPTION_LEN = void 0;
4
+ const buffer_layout_1 = require("@solana/buffer-layout");
5
+ const buffer_layout_utils_1 = require("@solana/buffer-layout-utils");
6
+ exports.MAX_DESCRIPTION_LEN = 32;
7
+ exports.transmissionsLayout = (0, buffer_layout_1.struct)([
8
+ (0, buffer_layout_1.u8)("version"),
9
+ (0, buffer_layout_1.u8)("state"),
10
+ (0, buffer_layout_utils_1.publicKey)("owner"),
11
+ (0, buffer_layout_utils_1.publicKey)("proposedOwner"),
12
+ (0, buffer_layout_utils_1.publicKey)("writer"),
13
+ (0, buffer_layout_1.blob)(exports.MAX_DESCRIPTION_LEN, "description"),
14
+ (0, buffer_layout_1.u8)("decimals"),
15
+ (0, buffer_layout_1.u32)("flaggingThreshold"),
16
+ (0, buffer_layout_1.u32)("latestRoundId"),
17
+ (0, buffer_layout_1.u8)("granularity"),
18
+ (0, buffer_layout_1.u32)("liveLength"),
19
+ (0, buffer_layout_1.u32)("liveCursor"),
20
+ (0, buffer_layout_1.u32)("historicalCursor"),
21
+ ]);
22
+ //# sourceMappingURL=chainlink_types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chainlink_types.js","sourceRoot":"","sources":["../src/chainlink_types.ts"],"names":[],"mappings":";;;AACA,yDAA6D;AAC7D,qEAAuD;AAkB1C,QAAA,mBAAmB,GAAG,EAAE,CAAA;AAExB,QAAA,mBAAmB,GAAG,IAAA,sBAAM,EAAgB;IACvD,IAAA,kBAAE,EAAC,SAAS,CAAC;IACb,IAAA,kBAAE,EAAC,OAAO,CAAC;IACX,IAAA,+BAAS,EAAC,OAAO,CAAC;IAClB,IAAA,+BAAS,EAAC,eAAe,CAAC;IAC1B,IAAA,+BAAS,EAAC,QAAQ,CAAC;IACnB,IAAA,oBAAI,EAAC,2BAAmB,EAAE,aAAa,CAAC;IACxC,IAAA,kBAAE,EAAC,UAAU,CAAC;IACd,IAAA,mBAAG,EAAC,mBAAmB,CAAC;IACxB,IAAA,mBAAG,EAAC,eAAe,CAAC;IACpB,IAAA,kBAAE,EAAC,aAAa,CAAC;IACjB,IAAA,mBAAG,EAAC,YAAY,CAAC;IACjB,IAAA,mBAAG,EAAC,YAAY,CAAC;IACjB,IAAA,mBAAG,EAAC,kBAAkB,CAAC;CACxB,CAAC,CAAA"}
@@ -0,0 +1,97 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { web3 } from "@coral-xyz/anchor";
4
+ import type { Transmissions } from "./chainlink_types";
5
+ export declare const IDL: {
6
+ version: string;
7
+ name: string;
8
+ constants: {
9
+ name: string;
10
+ type: {
11
+ defined: string;
12
+ };
13
+ value: string;
14
+ }[];
15
+ instructions: ({
16
+ name: string;
17
+ accounts: {
18
+ name: string;
19
+ isMut: boolean;
20
+ isSigner: boolean;
21
+ }[];
22
+ args: {
23
+ name: string;
24
+ type: string;
25
+ }[];
26
+ } | {
27
+ name: string;
28
+ accounts: {
29
+ name: string;
30
+ isMut: boolean;
31
+ isSigner: boolean;
32
+ }[];
33
+ args: {
34
+ name: string;
35
+ type: {
36
+ defined: string;
37
+ };
38
+ }[];
39
+ })[];
40
+ accounts: {
41
+ name: string;
42
+ type: {
43
+ kind: string;
44
+ fields: ({
45
+ name: string;
46
+ type: string;
47
+ } | {
48
+ name: string;
49
+ type: {
50
+ array: (string | number)[];
51
+ };
52
+ })[];
53
+ };
54
+ }[];
55
+ types: ({
56
+ name: string;
57
+ type: {
58
+ kind: string;
59
+ fields: {
60
+ name: string;
61
+ type: string;
62
+ }[];
63
+ variants?: undefined;
64
+ };
65
+ } | {
66
+ name: string;
67
+ type: {
68
+ kind: string;
69
+ variants: ({
70
+ name: string;
71
+ fields?: undefined;
72
+ } | {
73
+ name: string;
74
+ fields: {
75
+ name: string;
76
+ type: string;
77
+ }[];
78
+ })[];
79
+ fields?: undefined;
80
+ };
81
+ })[];
82
+ errors: ({
83
+ code: number;
84
+ name: string;
85
+ msg: string;
86
+ } | {
87
+ code: number;
88
+ name: string;
89
+ msg?: undefined;
90
+ })[];
91
+ };
92
+ export declare const PROGRAM_ID: web3.PublicKey;
93
+ export interface ChainlinkPriceData {
94
+ header: Transmissions;
95
+ answer: bigint;
96
+ }
97
+ export declare function decodeChainlinkPriceAccount(accountInfo: web3.AccountInfo<Buffer>): ChainlinkPriceData;
package/build/index.js ADDED
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.decodeChainlinkPriceAccount = exports.PROGRAM_ID = exports.IDL = void 0;
27
+ const anchor_1 = require("@coral-xyz/anchor");
28
+ const chainlinkIdl = __importStar(require("./chainlink.json"));
29
+ exports.IDL = chainlinkIdl;
30
+ exports.PROGRAM_ID = new anchor_1.web3.PublicKey("HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny");
31
+ const coder = new anchor_1.BorshCoder(chainlinkIdl);
32
+ const DISCRIMINATOR_LEN = 8;
33
+ const HEADER_SIZE = 192;
34
+ const TRANSMISSION_SIZE = 48;
35
+ const PRICE_OFFSET_WITHIN_TRANSMISSION = 16;
36
+ function decodeChainlinkPriceAccount(accountInfo) {
37
+ if (!accountInfo.owner.equals(exports.PROGRAM_ID)) {
38
+ throw new Error("Invalid Chainlink transmissions account owner");
39
+ }
40
+ const data = accountInfo.data;
41
+ const headerEnd = DISCRIMINATOR_LEN + HEADER_SIZE;
42
+ const transmissionsStart = headerEnd;
43
+ const minAccountSize = headerEnd + TRANSMISSION_SIZE;
44
+ if (data.length < minAccountSize) {
45
+ throw new Error("Chainlink transmissions account too small");
46
+ }
47
+ const headerData = data.subarray(0, headerEnd);
48
+ const header = coder.accounts.decode("Transmissions", headerData);
49
+ if (header.liveLength !== 1) {
50
+ throw new Error("Unsupported Chainlink transmissions layout");
51
+ }
52
+ if (header.latestRoundId === 0) {
53
+ throw new Error("Chainlink feed missing latest round");
54
+ }
55
+ const priceOffset = transmissionsStart + PRICE_OFFSET_WITHIN_TRANSMISSION;
56
+ const answer = readBigInt128LE(data, priceOffset);
57
+ if (answer < 0n) {
58
+ throw new Error("Chainlink price is negative");
59
+ }
60
+ return { header, answer };
61
+ }
62
+ exports.decodeChainlinkPriceAccount = decodeChainlinkPriceAccount;
63
+ function readBigInt128LE(buffer, offset) {
64
+ const low = buffer.readBigUInt64LE(offset);
65
+ const high = buffer.readBigInt64LE(offset + 8);
66
+ return (high << 64n) + low;
67
+ }
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAyD;AAEzD,+DAAgD;AAGnC,QAAA,GAAG,GAAG,YAAY,CAAA;AAClB,QAAA,UAAU,GAAG,IAAI,aAAI,CAAC,SAAS,CAAC,8CAA8C,CAAC,CAAA;AAE5F,MAAM,KAAK,GAAG,IAAI,mBAAU,CAAC,YAA8B,CAAC,CAAA;AAE5D,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAC3B,MAAM,WAAW,GAAG,GAAG,CAAA;AACvB,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAC5B,MAAM,gCAAgC,GAAG,EAAE,CAAA;AAO3C,SAAgB,2BAA2B,CAAC,WAAqC;IAC/E,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAU,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAClE,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAA;IAE7B,MAAM,SAAS,GAAG,iBAAiB,GAAG,WAAW,CAAA;IACjD,MAAM,kBAAkB,GAAG,SAAS,CAAA;IACpC,MAAM,cAAc,GAAG,SAAS,GAAG,iBAAiB,CAAA;IAEpD,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAgB,eAAe,EAAE,UAAU,CAAC,CAAA;IAEhF,IAAI,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IAED,IAAI,MAAM,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,GAAG,gCAAgC,CAAA;IACzE,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IAEjD,IAAI,MAAM,GAAG,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;AAC3B,CAAC;AAlCD,kEAkCC;AAED,SAAS,eAAe,CAAC,MAAc,EAAE,MAAc;IACrD,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC9C,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,GAAG,CAAA;AAC5B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@exponent-labs/chainlink-idl",
3
+ "version": "0.9.0",
4
+ "main": "build/index.js",
5
+ "types": "build/index.d.ts",
6
+ "license": "AGPL-3.0",
7
+ "scripts": {
8
+ "build": "tsc --build"
9
+ },
10
+ "dependencies": {
11
+ "@coral-xyz/anchor": "0.29.0"
12
+ },
13
+ "devDependencies": {
14
+ "typescript": "5.4.5"
15
+ }
16
+ }
@@ -0,0 +1,503 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "name": "store",
4
+ "constants": [
5
+ {
6
+ "name": "HEADER_SIZE",
7
+ "type": {
8
+ "defined": "usize"
9
+ },
10
+ "value": "192"
11
+ }
12
+ ],
13
+ "instructions": [
14
+ {
15
+ "name": "createFeed",
16
+ "accounts": [
17
+ {
18
+ "name": "feed",
19
+ "isMut": true,
20
+ "isSigner": false
21
+ },
22
+ {
23
+ "name": "authority",
24
+ "isMut": false,
25
+ "isSigner": true
26
+ }
27
+ ],
28
+ "args": [
29
+ {
30
+ "name": "description",
31
+ "type": "string"
32
+ },
33
+ {
34
+ "name": "decimals",
35
+ "type": "u8"
36
+ },
37
+ {
38
+ "name": "granularity",
39
+ "type": "u8"
40
+ },
41
+ {
42
+ "name": "liveLength",
43
+ "type": "u32"
44
+ }
45
+ ]
46
+ },
47
+ {
48
+ "name": "closeFeed",
49
+ "accounts": [
50
+ {
51
+ "name": "feed",
52
+ "isMut": true,
53
+ "isSigner": false
54
+ },
55
+ {
56
+ "name": "owner",
57
+ "isMut": false,
58
+ "isSigner": false
59
+ },
60
+ {
61
+ "name": "receiver",
62
+ "isMut": true,
63
+ "isSigner": false
64
+ },
65
+ {
66
+ "name": "authority",
67
+ "isMut": false,
68
+ "isSigner": true
69
+ }
70
+ ],
71
+ "args": []
72
+ },
73
+ {
74
+ "name": "transferFeedOwnership",
75
+ "accounts": [
76
+ {
77
+ "name": "feed",
78
+ "isMut": true,
79
+ "isSigner": false
80
+ },
81
+ {
82
+ "name": "owner",
83
+ "isMut": false,
84
+ "isSigner": false
85
+ },
86
+ {
87
+ "name": "authority",
88
+ "isMut": false,
89
+ "isSigner": true
90
+ }
91
+ ],
92
+ "args": [
93
+ {
94
+ "name": "proposedOwner",
95
+ "type": "publicKey"
96
+ }
97
+ ]
98
+ },
99
+ {
100
+ "name": "acceptFeedOwnership",
101
+ "accounts": [
102
+ {
103
+ "name": "feed",
104
+ "isMut": true,
105
+ "isSigner": false
106
+ },
107
+ {
108
+ "name": "proposedOwner",
109
+ "isMut": false,
110
+ "isSigner": false
111
+ },
112
+ {
113
+ "name": "authority",
114
+ "isMut": false,
115
+ "isSigner": true
116
+ }
117
+ ],
118
+ "args": []
119
+ },
120
+ {
121
+ "name": "setValidatorConfig",
122
+ "accounts": [
123
+ {
124
+ "name": "feed",
125
+ "isMut": true,
126
+ "isSigner": false
127
+ },
128
+ {
129
+ "name": "owner",
130
+ "isMut": false,
131
+ "isSigner": false
132
+ },
133
+ {
134
+ "name": "authority",
135
+ "isMut": false,
136
+ "isSigner": true
137
+ }
138
+ ],
139
+ "args": [
140
+ {
141
+ "name": "flaggingThreshold",
142
+ "type": "u32"
143
+ }
144
+ ]
145
+ },
146
+ {
147
+ "name": "setWriter",
148
+ "accounts": [
149
+ {
150
+ "name": "feed",
151
+ "isMut": true,
152
+ "isSigner": false
153
+ },
154
+ {
155
+ "name": "owner",
156
+ "isMut": false,
157
+ "isSigner": false
158
+ },
159
+ {
160
+ "name": "authority",
161
+ "isMut": false,
162
+ "isSigner": true
163
+ }
164
+ ],
165
+ "args": [
166
+ {
167
+ "name": "writer",
168
+ "type": "publicKey"
169
+ }
170
+ ]
171
+ },
172
+ {
173
+ "name": "lowerFlag",
174
+ "accounts": [
175
+ {
176
+ "name": "feed",
177
+ "isMut": true,
178
+ "isSigner": false
179
+ },
180
+ {
181
+ "name": "owner",
182
+ "isMut": false,
183
+ "isSigner": false
184
+ },
185
+ {
186
+ "name": "authority",
187
+ "isMut": false,
188
+ "isSigner": true
189
+ },
190
+ {
191
+ "name": "accessController",
192
+ "isMut": false,
193
+ "isSigner": false
194
+ }
195
+ ],
196
+ "args": []
197
+ },
198
+ {
199
+ "name": "submit",
200
+ "accounts": [
201
+ {
202
+ "name": "feed",
203
+ "isMut": true,
204
+ "isSigner": false
205
+ },
206
+ {
207
+ "name": "authority",
208
+ "isMut": false,
209
+ "isSigner": true
210
+ }
211
+ ],
212
+ "args": [
213
+ {
214
+ "name": "round",
215
+ "type": {
216
+ "defined": "NewTransmission"
217
+ }
218
+ }
219
+ ]
220
+ },
221
+ {
222
+ "name": "initialize",
223
+ "accounts": [
224
+ {
225
+ "name": "store",
226
+ "isMut": true,
227
+ "isSigner": false
228
+ },
229
+ {
230
+ "name": "owner",
231
+ "isMut": false,
232
+ "isSigner": true
233
+ },
234
+ {
235
+ "name": "loweringAccessController",
236
+ "isMut": false,
237
+ "isSigner": false
238
+ }
239
+ ],
240
+ "args": []
241
+ },
242
+ {
243
+ "name": "transferStoreOwnership",
244
+ "accounts": [
245
+ {
246
+ "name": "store",
247
+ "isMut": true,
248
+ "isSigner": false
249
+ },
250
+ {
251
+ "name": "authority",
252
+ "isMut": false,
253
+ "isSigner": true
254
+ }
255
+ ],
256
+ "args": [
257
+ {
258
+ "name": "proposedOwner",
259
+ "type": "publicKey"
260
+ }
261
+ ]
262
+ },
263
+ {
264
+ "name": "acceptStoreOwnership",
265
+ "accounts": [
266
+ {
267
+ "name": "store",
268
+ "isMut": true,
269
+ "isSigner": false
270
+ },
271
+ {
272
+ "name": "authority",
273
+ "isMut": false,
274
+ "isSigner": true
275
+ }
276
+ ],
277
+ "args": []
278
+ },
279
+ {
280
+ "name": "setLoweringAccessController",
281
+ "accounts": [
282
+ {
283
+ "name": "store",
284
+ "isMut": true,
285
+ "isSigner": false
286
+ },
287
+ {
288
+ "name": "authority",
289
+ "isMut": false,
290
+ "isSigner": true
291
+ },
292
+ {
293
+ "name": "accessController",
294
+ "isMut": false,
295
+ "isSigner": false
296
+ }
297
+ ],
298
+ "args": []
299
+ },
300
+ {
301
+ "name": "query",
302
+ "accounts": [
303
+ {
304
+ "name": "feed",
305
+ "isMut": false,
306
+ "isSigner": false
307
+ }
308
+ ],
309
+ "args": [
310
+ {
311
+ "name": "scope",
312
+ "type": {
313
+ "defined": "Scope"
314
+ }
315
+ }
316
+ ]
317
+ }
318
+ ],
319
+ "accounts": [
320
+ {
321
+ "name": "Store",
322
+ "type": {
323
+ "kind": "struct",
324
+ "fields": [
325
+ {
326
+ "name": "owner",
327
+ "type": "publicKey"
328
+ },
329
+ {
330
+ "name": "proposedOwner",
331
+ "type": "publicKey"
332
+ },
333
+ {
334
+ "name": "loweringAccessController",
335
+ "type": "publicKey"
336
+ }
337
+ ]
338
+ }
339
+ },
340
+ {
341
+ "name": "Transmissions",
342
+ "type": {
343
+ "kind": "struct",
344
+ "fields": [
345
+ {
346
+ "name": "version",
347
+ "type": "u8"
348
+ },
349
+ {
350
+ "name": "state",
351
+ "type": "u8"
352
+ },
353
+ {
354
+ "name": "owner",
355
+ "type": "publicKey"
356
+ },
357
+ {
358
+ "name": "proposedOwner",
359
+ "type": "publicKey"
360
+ },
361
+ {
362
+ "name": "writer",
363
+ "type": "publicKey"
364
+ },
365
+ {
366
+ "name": "description",
367
+ "type": {
368
+ "array": ["u8", 32]
369
+ }
370
+ },
371
+ {
372
+ "name": "decimals",
373
+ "type": "u8"
374
+ },
375
+ {
376
+ "name": "flaggingThreshold",
377
+ "type": "u32"
378
+ },
379
+ {
380
+ "name": "latestRoundId",
381
+ "type": "u32"
382
+ },
383
+ {
384
+ "name": "granularity",
385
+ "type": "u8"
386
+ },
387
+ {
388
+ "name": "liveLength",
389
+ "type": "u32"
390
+ },
391
+ {
392
+ "name": "liveCursor",
393
+ "type": "u32"
394
+ },
395
+ {
396
+ "name": "historicalCursor",
397
+ "type": "u32"
398
+ }
399
+ ]
400
+ }
401
+ }
402
+ ],
403
+ "types": [
404
+ {
405
+ "name": "NewTransmission",
406
+ "type": {
407
+ "kind": "struct",
408
+ "fields": [
409
+ {
410
+ "name": "timestamp",
411
+ "type": "u64"
412
+ },
413
+ {
414
+ "name": "answer",
415
+ "type": "i128"
416
+ }
417
+ ]
418
+ }
419
+ },
420
+ {
421
+ "name": "Round",
422
+ "type": {
423
+ "kind": "struct",
424
+ "fields": [
425
+ {
426
+ "name": "roundId",
427
+ "type": "u32"
428
+ },
429
+ {
430
+ "name": "slot",
431
+ "type": "u64"
432
+ },
433
+ {
434
+ "name": "timestamp",
435
+ "type": "u32"
436
+ },
437
+ {
438
+ "name": "answer",
439
+ "type": "i128"
440
+ }
441
+ ]
442
+ }
443
+ },
444
+ {
445
+ "name": "Scope",
446
+ "type": {
447
+ "kind": "enum",
448
+ "variants": [
449
+ {
450
+ "name": "Version"
451
+ },
452
+ {
453
+ "name": "Decimals"
454
+ },
455
+ {
456
+ "name": "Description"
457
+ },
458
+ {
459
+ "name": "RoundData",
460
+ "fields": [
461
+ {
462
+ "name": "round_id",
463
+ "type": "u32"
464
+ }
465
+ ]
466
+ },
467
+ {
468
+ "name": "LatestRoundData"
469
+ },
470
+ {
471
+ "name": "Aggregator"
472
+ }
473
+ ]
474
+ }
475
+ }
476
+ ],
477
+ "errors": [
478
+ {
479
+ "code": 6000,
480
+ "name": "Unauthorized",
481
+ "msg": "Unauthorized"
482
+ },
483
+ {
484
+ "code": 6001,
485
+ "name": "InvalidInput",
486
+ "msg": "Invalid input"
487
+ },
488
+ {
489
+ "code": 6002,
490
+ "name": "NotFound"
491
+ },
492
+ {
493
+ "code": 6003,
494
+ "name": "InvalidVersion",
495
+ "msg": "Invalid version"
496
+ },
497
+ {
498
+ "code": 6004,
499
+ "name": "InsufficientSize",
500
+ "msg": "Insufficient or invalid feed account size, has to be `8 + HEADER_SIZE + n * size_of::<Transmission>()`"
501
+ }
502
+ ]
503
+ }
@@ -0,0 +1,37 @@
1
+ import { web3 } from "@coral-xyz/anchor"
2
+ import { blob, struct, u8, u32 } from "@solana/buffer-layout"
3
+ import { publicKey } from "@solana/buffer-layout-utils"
4
+
5
+ export interface Transmissions {
6
+ version: number
7
+ state: number
8
+ owner: web3.PublicKey
9
+ proposedOwner: web3.PublicKey
10
+ writer: web3.PublicKey
11
+ description: Uint8Array
12
+ decimals: number
13
+ flaggingThreshold: number
14
+ latestRoundId: number
15
+ granularity: number
16
+ liveLength: number
17
+ liveCursor: number
18
+ historicalCursor: number
19
+ }
20
+
21
+ export const MAX_DESCRIPTION_LEN = 32
22
+
23
+ export const transmissionsLayout = struct<Transmissions>([
24
+ u8("version"),
25
+ u8("state"),
26
+ publicKey("owner"),
27
+ publicKey("proposedOwner"),
28
+ publicKey("writer"),
29
+ blob(MAX_DESCRIPTION_LEN, "description"),
30
+ u8("decimals"),
31
+ u32("flaggingThreshold"),
32
+ u32("latestRoundId"),
33
+ u8("granularity"),
34
+ u32("liveLength"),
35
+ u32("liveCursor"),
36
+ u32("historicalCursor"),
37
+ ])
package/src/index.ts ADDED
@@ -0,0 +1,61 @@
1
+ import { BorshCoder, Idl, web3 } from "@coral-xyz/anchor"
2
+
3
+ import * as chainlinkIdl from "./chainlink.json"
4
+ import type { Transmissions } from "./chainlink_types"
5
+
6
+ export const IDL = chainlinkIdl
7
+ export const PROGRAM_ID = new web3.PublicKey("HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny")
8
+
9
+ const coder = new BorshCoder(chainlinkIdl as unknown as Idl)
10
+
11
+ const DISCRIMINATOR_LEN = 8
12
+ const HEADER_SIZE = 192
13
+ const TRANSMISSION_SIZE = 48
14
+ const PRICE_OFFSET_WITHIN_TRANSMISSION = 16
15
+
16
+ export interface ChainlinkPriceData {
17
+ header: Transmissions
18
+ answer: bigint
19
+ }
20
+
21
+ export function decodeChainlinkPriceAccount(accountInfo: web3.AccountInfo<Buffer>): ChainlinkPriceData {
22
+ if (!accountInfo.owner.equals(PROGRAM_ID)) {
23
+ throw new Error("Invalid Chainlink transmissions account owner")
24
+ }
25
+
26
+ const data = accountInfo.data
27
+
28
+ const headerEnd = DISCRIMINATOR_LEN + HEADER_SIZE
29
+ const transmissionsStart = headerEnd
30
+ const minAccountSize = headerEnd + TRANSMISSION_SIZE
31
+
32
+ if (data.length < minAccountSize) {
33
+ throw new Error("Chainlink transmissions account too small")
34
+ }
35
+
36
+ const headerData = data.subarray(0, headerEnd)
37
+ const header = coder.accounts.decode<Transmissions>("Transmissions", headerData)
38
+
39
+ if (header.liveLength !== 1) {
40
+ throw new Error("Unsupported Chainlink transmissions layout")
41
+ }
42
+
43
+ if (header.latestRoundId === 0) {
44
+ throw new Error("Chainlink feed missing latest round")
45
+ }
46
+
47
+ const priceOffset = transmissionsStart + PRICE_OFFSET_WITHIN_TRANSMISSION
48
+ const answer = readBigInt128LE(data, priceOffset)
49
+
50
+ if (answer < 0n) {
51
+ throw new Error("Chainlink price is negative")
52
+ }
53
+
54
+ return { header, answer }
55
+ }
56
+
57
+ function readBigInt128LE(buffer: Buffer, offset: number): bigint {
58
+ const low = buffer.readBigUInt64LE(offset)
59
+ const high = buffer.readBigInt64LE(offset + 8)
60
+ return (high << 64n) + low
61
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "files": ["src/index.ts", "src/chainlink.json", "src/chainlink_types.ts"],
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "sourceMap": true,
6
+ "incremental": true,
7
+ "composite": true,
8
+ "target": "ESNext",
9
+ "module": "CommonJS",
10
+ "declaration": true,
11
+ "outDir": "./build",
12
+ "esModuleInterop": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "skipLibCheck": true,
15
+ "resolveJsonModule": true
16
+ }
17
+ }