s0racle-sdk 0.0.1

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/dist/index.js ADDED
@@ -0,0 +1,2192 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ PROGRAM_ID: () => PROGRAM_ID,
34
+ Region: () => Region,
35
+ clientDiversityIndex: () => clientDiversityIndex,
36
+ createS0racleClient: () => createS0racleClient,
37
+ dominantClient: () => dominantClient,
38
+ getNetworkHealthPDA: () => getNetworkHealthPDA,
39
+ getObserverPDA: () => getObserverPDA,
40
+ getRegistryPDA: () => getRegistryPDA,
41
+ healthStatus: () => healthStatus,
42
+ isConsensusCritical: () => isConsensusCritical,
43
+ isDegraded: () => isDegraded,
44
+ isObserverStale: () => isObserverStale,
45
+ isStale: () => isStale,
46
+ lamportsToSol: () => lamportsToSol,
47
+ latencyScore: () => latencyScore,
48
+ regionLabel: () => regionLabel,
49
+ stakeReachStatus: () => stakeReachStatus
50
+ });
51
+ module.exports = __toCommonJS(index_exports);
52
+
53
+ // src/types.ts
54
+ var import_web3 = require("@solana/web3.js");
55
+ var Region = /* @__PURE__ */ ((Region2) => {
56
+ Region2["Asia"] = "Asia";
57
+ Region2["US"] = "US";
58
+ Region2["EU"] = "EU";
59
+ Region2["SouthAmerica"] = "SouthAmerica";
60
+ Region2["Africa"] = "Africa";
61
+ Region2["Oceania"] = "Oceania";
62
+ Region2["Other"] = "Other";
63
+ return Region2;
64
+ })(Region || {});
65
+
66
+ // src/accounts.ts
67
+ var import_web32 = require("@solana/web3.js");
68
+ var import_bn = require("bn.js");
69
+ var PROGRAM_ID = new import_web32.PublicKey(
70
+ "2paXpX8Ze3tvYezviSwQJSSihG3LbrDiD7SNsaFwgTow"
71
+ );
72
+ var STALE_SLOTS = 150n;
73
+ var SUPPORTED_REGISTRY_VERSION = 1;
74
+ function getRegistryPDA(programId = PROGRAM_ID) {
75
+ return import_web32.PublicKey.findProgramAddressSync([Buffer.from("registry")], programId);
76
+ }
77
+ function getNetworkHealthPDA(programId = PROGRAM_ID) {
78
+ return import_web32.PublicKey.findProgramAddressSync(
79
+ [Buffer.from("network_health")],
80
+ programId
81
+ );
82
+ }
83
+ function getObserverPDA(observer, programId = PROGRAM_ID) {
84
+ return import_web32.PublicKey.findProgramAddressSync(
85
+ [Buffer.from("observer"), observer.toBuffer()],
86
+ programId
87
+ );
88
+ }
89
+ function toBigInt(val) {
90
+ if (typeof val === "bigint") return val;
91
+ if (typeof val === "number") return BigInt(val);
92
+ return BigInt(val.toString());
93
+ }
94
+ function toRegion(val) {
95
+ const key = typeof val === "string" ? val : Object.keys(val)[0] ?? "other";
96
+ const normalized = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
97
+ const map = {
98
+ Asia: "Asia",
99
+ Us: "US",
100
+ Eu: "EU",
101
+ Southamerica: "SouthAmerica",
102
+ Africa: "Africa",
103
+ Oceania: "Oceania",
104
+ Other: "Other"
105
+ };
106
+ return map[normalized] ?? "Other";
107
+ }
108
+ function decodeAttestation(raw) {
109
+ return {
110
+ slot: toBigInt(raw["slot"]),
111
+ timestamp: toBigInt(raw["timestamp"]),
112
+ avgRttUs: raw["avgRttUs"],
113
+ p95RttUs: raw["p95RttUs"],
114
+ slotLatencyMs: raw["slotLatencyMs"],
115
+ tpuReachable: raw["tpuReachable"],
116
+ tpuProbed: raw["tpuProbed"],
117
+ agaveCount: raw["agaveCount"],
118
+ firedancerCount: raw["firedancerCount"],
119
+ jitoCount: raw["jitoCount"],
120
+ solanaLabsCount: raw["solanaLabsCount"],
121
+ otherCount: raw["otherCount"],
122
+ reachableStakePct: raw["reachableStakePct"]
123
+ };
124
+ }
125
+ function decodeRegionScore(raw) {
126
+ return {
127
+ region: toRegion(raw["region"]),
128
+ observerCount: raw["observerCount"],
129
+ healthScore: raw["healthScore"],
130
+ reachabilityPct: raw["reachabilityPct"],
131
+ avgRttUs: raw["avgRttUs"],
132
+ slotLatencyMs: raw["slotLatencyMs"],
133
+ lastUpdatedSlot: toBigInt(raw["lastUpdatedSlot"]),
134
+ agaveCount: raw["agaveCount"],
135
+ firedancerCount: raw["firedancerCount"],
136
+ jitoCount: raw["jitoCount"],
137
+ solanaLabsCount: raw["solanaLabsCount"],
138
+ otherCount: raw["otherCount"],
139
+ reachableStakePct: raw["reachableStakePct"]
140
+ };
141
+ }
142
+ function decodeNetworkHealth(raw) {
143
+ const minRaw = raw["minHealthEver"];
144
+ return {
145
+ healthScore: raw["healthScore"],
146
+ tpuReachabilityPct: raw["tpuReachabilityPct"],
147
+ avgSlotLatencyMs: raw["avgSlotLatencyMs"],
148
+ activeObserverCount: raw["activeObserverCount"],
149
+ activeRegionCount: raw["activeRegionCount"],
150
+ lastUpdatedSlot: toBigInt(raw["lastUpdatedSlot"]),
151
+ lastUpdatedTs: toBigInt(raw["lastUpdatedTs"]),
152
+ minHealthEver: minRaw === 255 ? null : minRaw,
153
+ maxHealthEver: raw["maxHealthEver"],
154
+ totalAttestations: toBigInt(raw["totalAttestations"]),
155
+ regionScores: raw["regionScores"].map(
156
+ decodeRegionScore
157
+ ),
158
+ agaveCount: raw["agaveCount"],
159
+ firedancerCount: raw["firedancerCount"],
160
+ jitoCount: raw["jitoCount"],
161
+ solanaLabsCount: raw["solanaLabsCount"],
162
+ otherCount: raw["otherCount"]
163
+ };
164
+ }
165
+ function decodeObserver(raw, publicKey) {
166
+ return {
167
+ publicKey,
168
+ authority: raw["authority"],
169
+ region: toRegion(raw["region"]),
170
+ stakeLamports: toBigInt(raw["stakeLamports"]),
171
+ registeredAt: toBigInt(raw["registeredAt"]),
172
+ lastAttestationSlot: toBigInt(raw["lastAttestationSlot"]),
173
+ attestationCount: toBigInt(raw["attestationCount"]),
174
+ latestAttestation: decodeAttestation(
175
+ raw["latestAttestation"]
176
+ ),
177
+ isActive: raw["isActive"]
178
+ };
179
+ }
180
+ function decodeRegistry(raw) {
181
+ const version = raw["version"];
182
+ if (version !== SUPPORTED_REGISTRY_VERSION) {
183
+ console.warn(
184
+ `s0racle-sdk: registry version ${version} is not supported by this SDK (expected ${SUPPORTED_REGISTRY_VERSION}). Upgrade s0racle-sdk to a compatible version.`
185
+ );
186
+ }
187
+ const pending = raw["pendingAuthority"];
188
+ return {
189
+ authority: raw["authority"],
190
+ pendingAuthority: pending ?? null,
191
+ minStakeLamports: toBigInt(raw["minStakeLamports"]),
192
+ observerCount: raw["observerCount"],
193
+ activeCount: raw["activeCount"],
194
+ maxObservers: raw["maxObservers"],
195
+ paused: raw["paused"],
196
+ version: raw["version"]
197
+ };
198
+ }
199
+
200
+ // src/client.ts
201
+ var import_anchor2 = require("@coral-xyz/anchor");
202
+ var import_web35 = require("@solana/web3.js");
203
+
204
+ // src/idl/s0racle_program.json
205
+ var s0racle_program_default = {
206
+ address: "2paXpX8Ze3tvYezviSwQJSSihG3LbrDiD7SNsaFwgTow",
207
+ metadata: {
208
+ name: "s0racle_program",
209
+ version: "0.1.0",
210
+ spec: "0.1.0",
211
+ description: "Created with Anchor"
212
+ },
213
+ instructions: [
214
+ {
215
+ name: "accept_authority",
216
+ discriminator: [
217
+ 107,
218
+ 86,
219
+ 198,
220
+ 91,
221
+ 33,
222
+ 12,
223
+ 107,
224
+ 160
225
+ ],
226
+ accounts: [
227
+ {
228
+ name: "registry",
229
+ writable: true
230
+ },
231
+ {
232
+ name: "new_authority",
233
+ signer: true
234
+ }
235
+ ],
236
+ args: []
237
+ },
238
+ {
239
+ name: "crank_aggregation",
240
+ discriminator: [
241
+ 37,
242
+ 116,
243
+ 43,
244
+ 137,
245
+ 4,
246
+ 13,
247
+ 88,
248
+ 26
249
+ ],
250
+ accounts: [
251
+ {
252
+ name: "cranker",
253
+ signer: true
254
+ },
255
+ {
256
+ name: "network_health",
257
+ writable: true,
258
+ pda: {
259
+ seeds: [
260
+ {
261
+ kind: "const",
262
+ value: [
263
+ 110,
264
+ 101,
265
+ 116,
266
+ 119,
267
+ 111,
268
+ 114,
269
+ 107,
270
+ 95,
271
+ 104,
272
+ 101,
273
+ 97,
274
+ 108,
275
+ 116,
276
+ 104
277
+ ]
278
+ }
279
+ ]
280
+ }
281
+ },
282
+ {
283
+ name: "registry_account",
284
+ pda: {
285
+ seeds: [
286
+ {
287
+ kind: "const",
288
+ value: [
289
+ 114,
290
+ 101,
291
+ 103,
292
+ 105,
293
+ 115,
294
+ 116,
295
+ 114,
296
+ 121
297
+ ]
298
+ }
299
+ ]
300
+ }
301
+ },
302
+ {
303
+ name: "clock",
304
+ address: "SysvarC1ock11111111111111111111111111111111"
305
+ }
306
+ ],
307
+ args: []
308
+ },
309
+ {
310
+ name: "deregister_observer",
311
+ discriminator: [
312
+ 16,
313
+ 4,
314
+ 225,
315
+ 8,
316
+ 113,
317
+ 188,
318
+ 135,
319
+ 196
320
+ ],
321
+ accounts: [
322
+ {
323
+ name: "caller",
324
+ writable: true,
325
+ signer: true
326
+ },
327
+ {
328
+ name: "observer_wallet",
329
+ docs: [
330
+ "Recipient of returned stake lamports on deregistration."
331
+ ],
332
+ writable: true
333
+ },
334
+ {
335
+ name: "observer_account",
336
+ writable: true,
337
+ pda: {
338
+ seeds: [
339
+ {
340
+ kind: "const",
341
+ value: [
342
+ 111,
343
+ 98,
344
+ 115,
345
+ 101,
346
+ 114,
347
+ 118,
348
+ 101,
349
+ 114
350
+ ]
351
+ },
352
+ {
353
+ kind: "account",
354
+ path: "observer_wallet"
355
+ }
356
+ ]
357
+ }
358
+ },
359
+ {
360
+ name: "registry",
361
+ writable: true,
362
+ pda: {
363
+ seeds: [
364
+ {
365
+ kind: "const",
366
+ value: [
367
+ 114,
368
+ 101,
369
+ 103,
370
+ 105,
371
+ 115,
372
+ 116,
373
+ 114,
374
+ 121
375
+ ]
376
+ }
377
+ ]
378
+ }
379
+ },
380
+ {
381
+ name: "system_program",
382
+ address: "11111111111111111111111111111111"
383
+ }
384
+ ],
385
+ args: []
386
+ },
387
+ {
388
+ name: "initialize",
389
+ discriminator: [
390
+ 175,
391
+ 175,
392
+ 109,
393
+ 31,
394
+ 13,
395
+ 152,
396
+ 155,
397
+ 237
398
+ ],
399
+ accounts: [
400
+ {
401
+ name: "authority",
402
+ writable: true,
403
+ signer: true
404
+ },
405
+ {
406
+ name: "registry",
407
+ writable: true,
408
+ pda: {
409
+ seeds: [
410
+ {
411
+ kind: "const",
412
+ value: [
413
+ 114,
414
+ 101,
415
+ 103,
416
+ 105,
417
+ 115,
418
+ 116,
419
+ 114,
420
+ 121
421
+ ]
422
+ }
423
+ ]
424
+ }
425
+ },
426
+ {
427
+ name: "network_health",
428
+ writable: true,
429
+ pda: {
430
+ seeds: [
431
+ {
432
+ kind: "const",
433
+ value: [
434
+ 110,
435
+ 101,
436
+ 116,
437
+ 119,
438
+ 111,
439
+ 114,
440
+ 107,
441
+ 95,
442
+ 104,
443
+ 101,
444
+ 97,
445
+ 108,
446
+ 116,
447
+ 104
448
+ ]
449
+ }
450
+ ]
451
+ }
452
+ },
453
+ {
454
+ name: "system_program",
455
+ address: "11111111111111111111111111111111"
456
+ }
457
+ ],
458
+ args: [
459
+ {
460
+ name: "min_stake_lamports",
461
+ type: "u64"
462
+ },
463
+ {
464
+ name: "max_observers",
465
+ type: "u16"
466
+ }
467
+ ]
468
+ },
469
+ {
470
+ name: "propose_authority",
471
+ discriminator: [
472
+ 20,
473
+ 148,
474
+ 236,
475
+ 198,
476
+ 76,
477
+ 119,
478
+ 99,
479
+ 142
480
+ ],
481
+ accounts: [
482
+ {
483
+ name: "registry",
484
+ writable: true,
485
+ pda: {
486
+ seeds: [
487
+ {
488
+ kind: "const",
489
+ value: [
490
+ 114,
491
+ 101,
492
+ 103,
493
+ 105,
494
+ 115,
495
+ 116,
496
+ 114,
497
+ 121
498
+ ]
499
+ }
500
+ ]
501
+ }
502
+ },
503
+ {
504
+ name: "authority",
505
+ signer: true,
506
+ relations: [
507
+ "registry"
508
+ ]
509
+ }
510
+ ],
511
+ args: [
512
+ {
513
+ name: "new_authority",
514
+ type: "pubkey"
515
+ }
516
+ ]
517
+ },
518
+ {
519
+ name: "register_observer",
520
+ discriminator: [
521
+ 95,
522
+ 238,
523
+ 80,
524
+ 77,
525
+ 247,
526
+ 96,
527
+ 2,
528
+ 225
529
+ ],
530
+ accounts: [
531
+ {
532
+ name: "observer",
533
+ writable: true,
534
+ signer: true
535
+ },
536
+ {
537
+ name: "observer_account",
538
+ writable: true,
539
+ pda: {
540
+ seeds: [
541
+ {
542
+ kind: "const",
543
+ value: [
544
+ 111,
545
+ 98,
546
+ 115,
547
+ 101,
548
+ 114,
549
+ 118,
550
+ 101,
551
+ 114
552
+ ]
553
+ },
554
+ {
555
+ kind: "account",
556
+ path: "observer"
557
+ }
558
+ ]
559
+ }
560
+ },
561
+ {
562
+ name: "registry",
563
+ writable: true,
564
+ pda: {
565
+ seeds: [
566
+ {
567
+ kind: "const",
568
+ value: [
569
+ 114,
570
+ 101,
571
+ 103,
572
+ 105,
573
+ 115,
574
+ 116,
575
+ 114,
576
+ 121
577
+ ]
578
+ }
579
+ ]
580
+ }
581
+ },
582
+ {
583
+ name: "system_program",
584
+ address: "11111111111111111111111111111111"
585
+ }
586
+ ],
587
+ args: [
588
+ {
589
+ name: "region",
590
+ type: {
591
+ defined: {
592
+ name: "Region"
593
+ }
594
+ }
595
+ }
596
+ ]
597
+ },
598
+ {
599
+ name: "slash_observer",
600
+ discriminator: [
601
+ 203,
602
+ 50,
603
+ 98,
604
+ 246,
605
+ 173,
606
+ 53,
607
+ 118,
608
+ 177
609
+ ],
610
+ accounts: [
611
+ {
612
+ name: "authority",
613
+ signer: true,
614
+ relations: [
615
+ "registry"
616
+ ]
617
+ },
618
+ {
619
+ name: "observer_wallet"
620
+ },
621
+ {
622
+ name: "observer_account",
623
+ writable: true,
624
+ pda: {
625
+ seeds: [
626
+ {
627
+ kind: "const",
628
+ value: [
629
+ 111,
630
+ 98,
631
+ 115,
632
+ 101,
633
+ 114,
634
+ 118,
635
+ 101,
636
+ 114
637
+ ]
638
+ },
639
+ {
640
+ kind: "account",
641
+ path: "observer_wallet"
642
+ }
643
+ ]
644
+ }
645
+ },
646
+ {
647
+ name: "registry",
648
+ writable: true,
649
+ pda: {
650
+ seeds: [
651
+ {
652
+ kind: "const",
653
+ value: [
654
+ 114,
655
+ 101,
656
+ 103,
657
+ 105,
658
+ 115,
659
+ 116,
660
+ 114,
661
+ 121
662
+ ]
663
+ }
664
+ ]
665
+ }
666
+ },
667
+ {
668
+ name: "treasury",
669
+ writable: true
670
+ }
671
+ ],
672
+ args: [
673
+ {
674
+ name: "slash_bps",
675
+ type: "u16"
676
+ }
677
+ ]
678
+ },
679
+ {
680
+ name: "submit_attestation",
681
+ discriminator: [
682
+ 238,
683
+ 220,
684
+ 255,
685
+ 105,
686
+ 183,
687
+ 211,
688
+ 40,
689
+ 83
690
+ ],
691
+ accounts: [
692
+ {
693
+ name: "authority",
694
+ writable: true,
695
+ signer: true,
696
+ relations: [
697
+ "observer_account"
698
+ ]
699
+ },
700
+ {
701
+ name: "observer_account",
702
+ writable: true,
703
+ pda: {
704
+ seeds: [
705
+ {
706
+ kind: "const",
707
+ value: [
708
+ 111,
709
+ 98,
710
+ 115,
711
+ 101,
712
+ 114,
713
+ 118,
714
+ 101,
715
+ 114
716
+ ]
717
+ },
718
+ {
719
+ kind: "account",
720
+ path: "authority"
721
+ }
722
+ ]
723
+ }
724
+ },
725
+ {
726
+ name: "network_health",
727
+ writable: true,
728
+ pda: {
729
+ seeds: [
730
+ {
731
+ kind: "const",
732
+ value: [
733
+ 110,
734
+ 101,
735
+ 116,
736
+ 119,
737
+ 111,
738
+ 114,
739
+ 107,
740
+ 95,
741
+ 104,
742
+ 101,
743
+ 97,
744
+ 108,
745
+ 116,
746
+ 104
747
+ ]
748
+ }
749
+ ]
750
+ }
751
+ },
752
+ {
753
+ name: "registry",
754
+ pda: {
755
+ seeds: [
756
+ {
757
+ kind: "const",
758
+ value: [
759
+ 114,
760
+ 101,
761
+ 103,
762
+ 105,
763
+ 115,
764
+ 116,
765
+ 114,
766
+ 121
767
+ ]
768
+ }
769
+ ]
770
+ }
771
+ },
772
+ {
773
+ name: "clock",
774
+ address: "SysvarC1ock11111111111111111111111111111111"
775
+ }
776
+ ],
777
+ args: [
778
+ {
779
+ name: "tpu_reachable",
780
+ type: "u16"
781
+ },
782
+ {
783
+ name: "tpu_probed",
784
+ type: "u16"
785
+ },
786
+ {
787
+ name: "avg_rtt_us",
788
+ type: "u32"
789
+ },
790
+ {
791
+ name: "p95_rtt_us",
792
+ type: "u32"
793
+ },
794
+ {
795
+ name: "slot_latency_ms",
796
+ type: "u32"
797
+ },
798
+ {
799
+ name: "agave_count",
800
+ type: "u16"
801
+ },
802
+ {
803
+ name: "firedancer_count",
804
+ type: "u16"
805
+ },
806
+ {
807
+ name: "jito_count",
808
+ type: "u16"
809
+ },
810
+ {
811
+ name: "solana_labs_count",
812
+ type: "u16"
813
+ },
814
+ {
815
+ name: "other_count",
816
+ type: "u16"
817
+ },
818
+ {
819
+ name: "reachable_stake_pct",
820
+ type: "u8"
821
+ }
822
+ ]
823
+ },
824
+ {
825
+ name: "update_config",
826
+ discriminator: [
827
+ 29,
828
+ 158,
829
+ 252,
830
+ 191,
831
+ 10,
832
+ 83,
833
+ 219,
834
+ 99
835
+ ],
836
+ accounts: [
837
+ {
838
+ name: "authority",
839
+ signer: true,
840
+ relations: [
841
+ "registry"
842
+ ]
843
+ },
844
+ {
845
+ name: "registry",
846
+ writable: true,
847
+ pda: {
848
+ seeds: [
849
+ {
850
+ kind: "const",
851
+ value: [
852
+ 114,
853
+ 101,
854
+ 103,
855
+ 105,
856
+ 115,
857
+ 116,
858
+ 114,
859
+ 121
860
+ ]
861
+ }
862
+ ]
863
+ }
864
+ }
865
+ ],
866
+ args: [
867
+ {
868
+ name: "min_stake_lamports",
869
+ type: {
870
+ option: "u64"
871
+ }
872
+ },
873
+ {
874
+ name: "max_observers",
875
+ type: {
876
+ option: "u16"
877
+ }
878
+ },
879
+ {
880
+ name: "paused",
881
+ type: {
882
+ option: "bool"
883
+ }
884
+ }
885
+ ]
886
+ }
887
+ ],
888
+ accounts: [
889
+ {
890
+ name: "NetworkHealthAccount",
891
+ discriminator: [
892
+ 90,
893
+ 218,
894
+ 55,
895
+ 105,
896
+ 239,
897
+ 131,
898
+ 43,
899
+ 68
900
+ ]
901
+ },
902
+ {
903
+ name: "ObserverAccount",
904
+ discriminator: [
905
+ 119,
906
+ 24,
907
+ 204,
908
+ 152,
909
+ 164,
910
+ 169,
911
+ 5,
912
+ 101
913
+ ]
914
+ },
915
+ {
916
+ name: "RegistryAccount",
917
+ discriminator: [
918
+ 113,
919
+ 93,
920
+ 106,
921
+ 201,
922
+ 100,
923
+ 166,
924
+ 146,
925
+ 98
926
+ ]
927
+ }
928
+ ],
929
+ events: [
930
+ {
931
+ name: "AttestationSubmitted",
932
+ discriminator: [
933
+ 177,
934
+ 213,
935
+ 117,
936
+ 225,
937
+ 166,
938
+ 11,
939
+ 54,
940
+ 218
941
+ ]
942
+ },
943
+ {
944
+ name: "ConfigUpdated",
945
+ discriminator: [
946
+ 40,
947
+ 241,
948
+ 230,
949
+ 122,
950
+ 11,
951
+ 19,
952
+ 198,
953
+ 194
954
+ ]
955
+ },
956
+ {
957
+ name: "ObserverDeregistered",
958
+ discriminator: [
959
+ 78,
960
+ 251,
961
+ 104,
962
+ 71,
963
+ 5,
964
+ 145,
965
+ 253,
966
+ 95
967
+ ]
968
+ },
969
+ {
970
+ name: "ObserverRegistered",
971
+ discriminator: [
972
+ 33,
973
+ 248,
974
+ 190,
975
+ 137,
976
+ 191,
977
+ 38,
978
+ 49,
979
+ 56
980
+ ]
981
+ },
982
+ {
983
+ name: "ObserverSlashed",
984
+ discriminator: [
985
+ 132,
986
+ 0,
987
+ 84,
988
+ 231,
989
+ 39,
990
+ 179,
991
+ 32,
992
+ 211
993
+ ]
994
+ }
995
+ ],
996
+ errors: [
997
+ {
998
+ code: 6e3,
999
+ name: "ValueCannotBeZero",
1000
+ msg: "Value cannot be zero"
1001
+ },
1002
+ {
1003
+ code: 6001,
1004
+ name: "RegistryPaused",
1005
+ msg: "Registry is currently paused"
1006
+ },
1007
+ {
1008
+ code: 6002,
1009
+ name: "MaxObserversReached",
1010
+ msg: "Maximum number of observers has been reached"
1011
+ },
1012
+ {
1013
+ code: 6003,
1014
+ name: "InsufficientLamports",
1015
+ msg: "Insufficient Lamports"
1016
+ },
1017
+ {
1018
+ code: 6004,
1019
+ name: "UnauthorizedObserver",
1020
+ msg: "Unauthorized Observer"
1021
+ },
1022
+ {
1023
+ code: 6005,
1024
+ name: "ObserverNotActive",
1025
+ msg: "Observer is not active"
1026
+ },
1027
+ {
1028
+ code: 6006,
1029
+ name: "ZeroValidatorsProbed",
1030
+ msg: "Zero validators probed"
1031
+ },
1032
+ {
1033
+ code: 6007,
1034
+ name: "InsufficientValidatorsProbed",
1035
+ msg: "Insufficient validators probed"
1036
+ },
1037
+ {
1038
+ code: 6008,
1039
+ name: "InvalidReachabilityCount",
1040
+ msg: "Invalid reachability count"
1041
+ },
1042
+ {
1043
+ code: 6009,
1044
+ name: "InvalidLatencyValue",
1045
+ msg: "Invalid latency submitted"
1046
+ },
1047
+ {
1048
+ code: 6010,
1049
+ name: "StaleAttestation",
1050
+ msg: "Stale attestation"
1051
+ },
1052
+ {
1053
+ code: 6011,
1054
+ name: "NoActiveObservers",
1055
+ msg: "No active observers"
1056
+ },
1057
+ {
1058
+ code: 6012,
1059
+ name: "ObserverAlreadyInActive",
1060
+ msg: "Observer already inactive"
1061
+ },
1062
+ {
1063
+ code: 6013,
1064
+ name: "UnAuthorizedCaller",
1065
+ msg: "Unauthorized caller"
1066
+ },
1067
+ {
1068
+ code: 6014,
1069
+ name: "InsufficientBalanceForRefund",
1070
+ msg: "Insufficient balance in PDA for stake refund"
1071
+ },
1072
+ {
1073
+ code: 6015,
1074
+ name: "InvalidSlashBps",
1075
+ msg: "Invalid slash basis points - must be <= 10000"
1076
+ },
1077
+ {
1078
+ code: 6016,
1079
+ name: "ObserverNotFound",
1080
+ msg: "Observer not found"
1081
+ },
1082
+ {
1083
+ code: 6017,
1084
+ name: "InsufficientBalanceForSlash",
1085
+ msg: "Insufficient balance in PDA for slash"
1086
+ },
1087
+ {
1088
+ code: 6018,
1089
+ name: "InvalidPendingAuthority",
1090
+ msg: "Invalid or no pending authority for registry"
1091
+ },
1092
+ {
1093
+ code: 6019,
1094
+ name: "MaxObserversCannotBeLessThanActiveObservers",
1095
+ msg: "Max observers cannot be less than active observers"
1096
+ }
1097
+ ],
1098
+ types: [
1099
+ {
1100
+ name: "Attestation",
1101
+ docs: [
1102
+ "Single 10-second measurement from one observer node"
1103
+ ],
1104
+ type: {
1105
+ kind: "struct",
1106
+ fields: [
1107
+ {
1108
+ name: "slot",
1109
+ docs: [
1110
+ "Solana slot this measurement covers"
1111
+ ],
1112
+ type: "u64"
1113
+ },
1114
+ {
1115
+ name: "timestamp",
1116
+ docs: [
1117
+ "Timestamp of the measurement"
1118
+ ],
1119
+ type: "i64"
1120
+ },
1121
+ {
1122
+ name: "avg_rtt_us",
1123
+ docs: [
1124
+ "Average RTT of the QUIC probe"
1125
+ ],
1126
+ type: "u32"
1127
+ },
1128
+ {
1129
+ name: "p95_rtt_us",
1130
+ docs: [
1131
+ "P95 RTT of the QUIC probe"
1132
+ ],
1133
+ type: "u32"
1134
+ },
1135
+ {
1136
+ name: "slot_latency_ms",
1137
+ docs: [
1138
+ "Slot latency of the QUIC probe"
1139
+ ],
1140
+ type: "u32"
1141
+ },
1142
+ {
1143
+ name: "tpu_reachable",
1144
+ docs: [
1145
+ "Validators reachable via QUIC probe"
1146
+ ],
1147
+ type: "u16"
1148
+ },
1149
+ {
1150
+ name: "tpu_probed",
1151
+ docs: [
1152
+ "Total validators probed this round"
1153
+ ],
1154
+ type: "u16"
1155
+ },
1156
+ {
1157
+ name: "agave_count",
1158
+ docs: [
1159
+ "Client distributions"
1160
+ ],
1161
+ type: "u16"
1162
+ },
1163
+ {
1164
+ name: "firedancer_count",
1165
+ type: "u16"
1166
+ },
1167
+ {
1168
+ name: "jito_count",
1169
+ type: "u16"
1170
+ },
1171
+ {
1172
+ name: "solana_labs_count",
1173
+ type: "u16"
1174
+ },
1175
+ {
1176
+ name: "other_count",
1177
+ type: "u16"
1178
+ },
1179
+ {
1180
+ name: "reachable_stake_pct",
1181
+ docs: [
1182
+ "% of total stake (by lamports) reachable via QUIC probe"
1183
+ ],
1184
+ type: "u8"
1185
+ }
1186
+ ]
1187
+ }
1188
+ },
1189
+ {
1190
+ name: "AttestationSubmitted",
1191
+ type: {
1192
+ kind: "struct",
1193
+ fields: [
1194
+ {
1195
+ name: "observer",
1196
+ type: "pubkey"
1197
+ },
1198
+ {
1199
+ name: "region",
1200
+ type: {
1201
+ defined: {
1202
+ name: "Region"
1203
+ }
1204
+ }
1205
+ },
1206
+ {
1207
+ name: "score",
1208
+ type: "u8"
1209
+ },
1210
+ {
1211
+ name: "reachability_pct",
1212
+ type: "u8"
1213
+ },
1214
+ {
1215
+ name: "slot_latency_ms",
1216
+ type: "u32"
1217
+ },
1218
+ {
1219
+ name: "slot",
1220
+ type: "u64"
1221
+ },
1222
+ {
1223
+ name: "agave_count",
1224
+ type: "u16"
1225
+ },
1226
+ {
1227
+ name: "firedancer_count",
1228
+ type: "u16"
1229
+ },
1230
+ {
1231
+ name: "jito_count",
1232
+ type: "u16"
1233
+ },
1234
+ {
1235
+ name: "solana_labs_count",
1236
+ type: "u16"
1237
+ },
1238
+ {
1239
+ name: "other_count",
1240
+ type: "u16"
1241
+ },
1242
+ {
1243
+ name: "reachable_stake_pct",
1244
+ type: "u8"
1245
+ }
1246
+ ]
1247
+ }
1248
+ },
1249
+ {
1250
+ name: "ConfigUpdated",
1251
+ type: {
1252
+ kind: "struct",
1253
+ fields: [
1254
+ {
1255
+ name: "min_stake_lamports",
1256
+ type: {
1257
+ option: "u64"
1258
+ }
1259
+ },
1260
+ {
1261
+ name: "max_observers",
1262
+ type: {
1263
+ option: "u16"
1264
+ }
1265
+ },
1266
+ {
1267
+ name: "paused",
1268
+ type: {
1269
+ option: "bool"
1270
+ }
1271
+ }
1272
+ ]
1273
+ }
1274
+ },
1275
+ {
1276
+ name: "NetworkHealthAccount",
1277
+ docs: [
1278
+ "Global oracle account - the single source of truth for dApps and UI reads"
1279
+ ],
1280
+ type: {
1281
+ kind: "struct",
1282
+ fields: [
1283
+ {
1284
+ name: "health_score",
1285
+ docs: [
1286
+ "The health score of the network"
1287
+ ],
1288
+ type: "u8"
1289
+ },
1290
+ {
1291
+ name: "tpu_reachability_pct",
1292
+ docs: [
1293
+ "TPU reachability % averaged across all regions"
1294
+ ],
1295
+ type: "u8"
1296
+ },
1297
+ {
1298
+ name: "avg_slot_latency_ms",
1299
+ docs: [
1300
+ "Average slot latency in milliseconds"
1301
+ ],
1302
+ type: "u32"
1303
+ },
1304
+ {
1305
+ name: "active_observer_count",
1306
+ docs: [
1307
+ "Number of active observers that contributed to this score"
1308
+ ],
1309
+ type: "u16"
1310
+ },
1311
+ {
1312
+ name: "active_region_count",
1313
+ docs: [
1314
+ "Number of regions with fresh attestations"
1315
+ ],
1316
+ type: "u16"
1317
+ },
1318
+ {
1319
+ name: "last_updated_slot",
1320
+ docs: [
1321
+ "Slot of last aggregation \u2014 dApps check this for staleness"
1322
+ ],
1323
+ type: "u64"
1324
+ },
1325
+ {
1326
+ name: "last_updated_ts",
1327
+ docs: [
1328
+ "Unix timestamp of last update"
1329
+ ],
1330
+ type: "i64"
1331
+ },
1332
+ {
1333
+ name: "min_health_ever",
1334
+ docs: [
1335
+ "Lowest health score ever recorded",
1336
+ 'Note: Initialized to 255 (u8::MAX) which represents "no data yet".'
1337
+ ],
1338
+ type: "u8"
1339
+ },
1340
+ {
1341
+ name: "max_health_ever",
1342
+ docs: [
1343
+ "Highest health score ever recorded"
1344
+ ],
1345
+ type: "u8"
1346
+ },
1347
+ {
1348
+ name: "total_attestations",
1349
+ docs: [
1350
+ "Total attestations ever submitted across all observers"
1351
+ ],
1352
+ type: "u64"
1353
+ },
1354
+ {
1355
+ name: "region_scores",
1356
+ docs: [
1357
+ "One entry per region"
1358
+ ],
1359
+ type: {
1360
+ array: [
1361
+ {
1362
+ defined: {
1363
+ name: "RegionScore"
1364
+ }
1365
+ },
1366
+ 7
1367
+ ]
1368
+ }
1369
+ },
1370
+ {
1371
+ name: "agave_count",
1372
+ type: "u8"
1373
+ },
1374
+ {
1375
+ name: "firedancer_count",
1376
+ type: "u8"
1377
+ },
1378
+ {
1379
+ name: "jito_count",
1380
+ type: "u8"
1381
+ },
1382
+ {
1383
+ name: "solana_labs_count",
1384
+ type: "u8"
1385
+ },
1386
+ {
1387
+ name: "other_count",
1388
+ type: "u8"
1389
+ },
1390
+ {
1391
+ name: "bump",
1392
+ docs: [
1393
+ "PDA bump seed"
1394
+ ],
1395
+ type: "u8"
1396
+ }
1397
+ ]
1398
+ }
1399
+ },
1400
+ {
1401
+ name: "ObserverAccount",
1402
+ docs: [
1403
+ "Per-observer state - stores identity, region, stake and latest measurement"
1404
+ ],
1405
+ type: {
1406
+ kind: "struct",
1407
+ fields: [
1408
+ {
1409
+ name: "authority",
1410
+ docs: [
1411
+ "The authority of the observer"
1412
+ ],
1413
+ type: "pubkey"
1414
+ },
1415
+ {
1416
+ name: "region",
1417
+ docs: [
1418
+ "The region of the observer"
1419
+ ],
1420
+ type: {
1421
+ defined: {
1422
+ name: "Region"
1423
+ }
1424
+ }
1425
+ },
1426
+ {
1427
+ name: "stake_lamports",
1428
+ docs: [
1429
+ "The stake of the observer"
1430
+ ],
1431
+ type: "u64"
1432
+ },
1433
+ {
1434
+ name: "registered_at",
1435
+ docs: [
1436
+ "The timestamp when the observer was registered"
1437
+ ],
1438
+ type: "i64"
1439
+ },
1440
+ {
1441
+ name: "last_attestation_slot",
1442
+ docs: [
1443
+ "Solana slot of the most recent attestation submitted",
1444
+ "Used for staleness check in crank_aggregation"
1445
+ ],
1446
+ type: "u64"
1447
+ },
1448
+ {
1449
+ name: "attestation_count",
1450
+ docs: [
1451
+ "The number of attestations submitted by the observer"
1452
+ ],
1453
+ type: "u64"
1454
+ },
1455
+ {
1456
+ name: "latest_attestation",
1457
+ docs: [
1458
+ "The latest attestation submitted by the observer"
1459
+ ],
1460
+ type: {
1461
+ defined: {
1462
+ name: "Attestation"
1463
+ }
1464
+ }
1465
+ },
1466
+ {
1467
+ name: "is_active",
1468
+ docs: [
1469
+ "Whether the observer is active"
1470
+ ],
1471
+ type: "bool"
1472
+ },
1473
+ {
1474
+ name: "bump",
1475
+ docs: [
1476
+ "The bump seed for the PDA"
1477
+ ],
1478
+ type: "u8"
1479
+ }
1480
+ ]
1481
+ }
1482
+ },
1483
+ {
1484
+ name: "ObserverDeregistered",
1485
+ type: {
1486
+ kind: "struct",
1487
+ fields: [
1488
+ {
1489
+ name: "observer",
1490
+ type: "pubkey"
1491
+ }
1492
+ ]
1493
+ }
1494
+ },
1495
+ {
1496
+ name: "ObserverRegistered",
1497
+ type: {
1498
+ kind: "struct",
1499
+ fields: [
1500
+ {
1501
+ name: "observer",
1502
+ type: "pubkey"
1503
+ },
1504
+ {
1505
+ name: "region",
1506
+ type: {
1507
+ defined: {
1508
+ name: "Region"
1509
+ }
1510
+ }
1511
+ },
1512
+ {
1513
+ name: "stake_lamports",
1514
+ type: "u64"
1515
+ }
1516
+ ]
1517
+ }
1518
+ },
1519
+ {
1520
+ name: "ObserverSlashed",
1521
+ type: {
1522
+ kind: "struct",
1523
+ fields: [
1524
+ {
1525
+ name: "observer",
1526
+ type: "pubkey"
1527
+ },
1528
+ {
1529
+ name: "slash_bps",
1530
+ type: "u16"
1531
+ },
1532
+ {
1533
+ name: "amount_slashed",
1534
+ type: "u64"
1535
+ }
1536
+ ]
1537
+ }
1538
+ },
1539
+ {
1540
+ name: "Region",
1541
+ docs: [
1542
+ "Geographic region of an observer node - serializes as u8 on-chain"
1543
+ ],
1544
+ type: {
1545
+ kind: "enum",
1546
+ variants: [
1547
+ {
1548
+ name: "Asia"
1549
+ },
1550
+ {
1551
+ name: "US"
1552
+ },
1553
+ {
1554
+ name: "EU"
1555
+ },
1556
+ {
1557
+ name: "SouthAmerica"
1558
+ },
1559
+ {
1560
+ name: "Africa"
1561
+ },
1562
+ {
1563
+ name: "Oceania"
1564
+ },
1565
+ {
1566
+ name: "Other"
1567
+ }
1568
+ ]
1569
+ }
1570
+ },
1571
+ {
1572
+ name: "RegionScore",
1573
+ docs: [
1574
+ "Health snapshot for one geographic region - embedded in NetworkHealthAccount"
1575
+ ],
1576
+ type: {
1577
+ kind: "struct",
1578
+ fields: [
1579
+ {
1580
+ name: "region",
1581
+ docs: [
1582
+ "Which region this entry represents"
1583
+ ],
1584
+ type: {
1585
+ defined: {
1586
+ name: "Region"
1587
+ }
1588
+ }
1589
+ },
1590
+ {
1591
+ name: "observer_count",
1592
+ docs: [
1593
+ "Number of observer contributions currently represented in this region aggregate"
1594
+ ],
1595
+ type: "u16"
1596
+ },
1597
+ {
1598
+ name: "health_score",
1599
+ docs: [
1600
+ "Health score from this region"
1601
+ ],
1602
+ type: "u8"
1603
+ },
1604
+ {
1605
+ name: "reachability_pct",
1606
+ docs: [
1607
+ "TPU reachability % from this region"
1608
+ ],
1609
+ type: "u8"
1610
+ },
1611
+ {
1612
+ name: "avg_rtt_us",
1613
+ docs: [
1614
+ "Average RTT from this region in microseconds"
1615
+ ],
1616
+ type: "u32"
1617
+ },
1618
+ {
1619
+ name: "slot_latency_ms",
1620
+ docs: [
1621
+ "Slot propagation latency from this region (ms)"
1622
+ ],
1623
+ type: "u32"
1624
+ },
1625
+ {
1626
+ name: "last_updated_slot",
1627
+ docs: [
1628
+ "Slot when this region last reported"
1629
+ ],
1630
+ type: "u64"
1631
+ },
1632
+ {
1633
+ name: "total_health_score",
1634
+ docs: [
1635
+ "Running total of health scores for observers in this region"
1636
+ ],
1637
+ type: "u32"
1638
+ },
1639
+ {
1640
+ name: "total_reachability_pct",
1641
+ docs: [
1642
+ "Running total of reachability percentages for observers in this region"
1643
+ ],
1644
+ type: "u32"
1645
+ },
1646
+ {
1647
+ name: "total_avg_rtt_us",
1648
+ docs: [
1649
+ "Running total of RTT values for observers in this region"
1650
+ ],
1651
+ type: "u64"
1652
+ },
1653
+ {
1654
+ name: "total_slot_latency_ms",
1655
+ docs: [
1656
+ "Running total of slot latency values for observers in this region"
1657
+ ],
1658
+ type: "u64"
1659
+ },
1660
+ {
1661
+ name: "agave_count",
1662
+ docs: [
1663
+ "Client distribution counts for this region"
1664
+ ],
1665
+ type: "u16"
1666
+ },
1667
+ {
1668
+ name: "firedancer_count",
1669
+ type: "u16"
1670
+ },
1671
+ {
1672
+ name: "jito_count",
1673
+ type: "u16"
1674
+ },
1675
+ {
1676
+ name: "solana_labs_count",
1677
+ type: "u16"
1678
+ },
1679
+ {
1680
+ name: "other_count",
1681
+ type: "u16"
1682
+ },
1683
+ {
1684
+ name: "total_agave_count",
1685
+ docs: [
1686
+ "Running totals"
1687
+ ],
1688
+ type: "u32"
1689
+ },
1690
+ {
1691
+ name: "total_firedancer_count",
1692
+ type: "u32"
1693
+ },
1694
+ {
1695
+ name: "total_jito_count",
1696
+ type: "u32"
1697
+ },
1698
+ {
1699
+ name: "total_solana_labs_count",
1700
+ type: "u32"
1701
+ },
1702
+ {
1703
+ name: "total_other_count",
1704
+ type: "u32"
1705
+ },
1706
+ {
1707
+ name: "reachable_stake_pct",
1708
+ docs: [
1709
+ "Stake-weighted reachability for this region"
1710
+ ],
1711
+ type: "u8"
1712
+ },
1713
+ {
1714
+ name: "total_reachable_stake_pct",
1715
+ type: "u32"
1716
+ }
1717
+ ]
1718
+ }
1719
+ },
1720
+ {
1721
+ name: "RegistryAccount",
1722
+ docs: [
1723
+ "Global registry - tracks all observer nodes and program config"
1724
+ ],
1725
+ type: {
1726
+ kind: "struct",
1727
+ fields: [
1728
+ {
1729
+ name: "authority",
1730
+ docs: [
1731
+ "Admin key"
1732
+ ],
1733
+ type: "pubkey"
1734
+ },
1735
+ {
1736
+ name: "pending_authority",
1737
+ docs: [
1738
+ "Pending authority for handoff"
1739
+ ],
1740
+ type: {
1741
+ option: "pubkey"
1742
+ }
1743
+ },
1744
+ {
1745
+ name: "min_stake_lamports",
1746
+ docs: [
1747
+ "Minimum stake required to observe"
1748
+ ],
1749
+ type: "u64"
1750
+ },
1751
+ {
1752
+ name: "observer_count",
1753
+ docs: [
1754
+ "Number of observers"
1755
+ ],
1756
+ type: "u16"
1757
+ },
1758
+ {
1759
+ name: "active_count",
1760
+ docs: [
1761
+ "Currently active accounts"
1762
+ ],
1763
+ type: "u16"
1764
+ },
1765
+ {
1766
+ name: "max_observers",
1767
+ docs: [
1768
+ "Maximum number of observers"
1769
+ ],
1770
+ type: "u16"
1771
+ },
1772
+ {
1773
+ name: "paused",
1774
+ docs: [
1775
+ "Paused flag"
1776
+ ],
1777
+ type: "bool"
1778
+ },
1779
+ {
1780
+ name: "version",
1781
+ docs: [
1782
+ "Version of the registry"
1783
+ ],
1784
+ type: "u8"
1785
+ },
1786
+ {
1787
+ name: "bump",
1788
+ docs: [
1789
+ "Bump seed for the PDA"
1790
+ ],
1791
+ type: "u8"
1792
+ }
1793
+ ]
1794
+ }
1795
+ }
1796
+ ],
1797
+ constants: [
1798
+ {
1799
+ name: "SEED",
1800
+ type: "string",
1801
+ value: '"anchor"'
1802
+ }
1803
+ ]
1804
+ };
1805
+
1806
+ // src/instructions.ts
1807
+ var import_anchor = require("@coral-xyz/anchor");
1808
+ var import_bn2 = __toESM(require("bn.js"));
1809
+ var import_web33 = require("@solana/web3.js");
1810
+ var CLOCK_SYSVAR = new import_web33.PublicKey(
1811
+ "SysvarC1ock11111111111111111111111111111111"
1812
+ );
1813
+ function toAnchorRegion(region) {
1814
+ const map = {
1815
+ ["Asia" /* Asia */]: "asia",
1816
+ ["US" /* US */]: "us",
1817
+ ["EU" /* EU */]: "eu",
1818
+ ["SouthAmerica" /* SouthAmerica */]: "southAmerica",
1819
+ ["Africa" /* Africa */]: "africa",
1820
+ ["Oceania" /* Oceania */]: "oceania",
1821
+ ["Other" /* Other */]: "other"
1822
+ };
1823
+ return { [map[region]]: {} };
1824
+ }
1825
+ async function buildRegisterObserver(program, observer, region) {
1826
+ const programId = program.programId;
1827
+ const [observerAccount] = getObserverPDA(observer, programId);
1828
+ const [registry] = getRegistryPDA(programId);
1829
+ return program.methods["registerObserver"](
1830
+ toAnchorRegion(region)
1831
+ ).accounts({ observer, observerAccount, registry }).instruction();
1832
+ }
1833
+ async function buildSubmitAttestation(program, authority, params) {
1834
+ const programId = program.programId;
1835
+ const [observerAccount] = getObserverPDA(authority, programId);
1836
+ const [networkHealth] = getNetworkHealthPDA(programId);
1837
+ const [registry] = getRegistryPDA(programId);
1838
+ return program.methods["submitAttestation"](
1839
+ params.tpuReachable,
1840
+ params.tpuProbed,
1841
+ params.avgRttUs,
1842
+ params.p95RttUs,
1843
+ params.slotLatencyMs,
1844
+ params.agaveCount,
1845
+ params.firedancerCount,
1846
+ params.jitoCount,
1847
+ params.solanaLabsCount,
1848
+ params.otherCount,
1849
+ params.reachableStakePct
1850
+ ).accounts({
1851
+ authority,
1852
+ observerAccount,
1853
+ networkHealth,
1854
+ registry,
1855
+ clock: CLOCK_SYSVAR
1856
+ }).instruction();
1857
+ }
1858
+ async function buildDeregisterObserver(program, caller, observerWallet) {
1859
+ const programId = program.programId;
1860
+ const [observerAccount] = getObserverPDA(observerWallet, programId);
1861
+ const [registry] = getRegistryPDA(programId);
1862
+ return program.methods["deregisterObserver"]().accounts({ caller, observerWallet, observerAccount, registry }).instruction();
1863
+ }
1864
+ async function buildCrankAggregation(program, cranker, observerAccounts) {
1865
+ const programId = program.programId;
1866
+ const [networkHealth] = getNetworkHealthPDA(programId);
1867
+ const [registryAccount] = getRegistryPDA(programId);
1868
+ const remaining = observerAccounts.map((pubkey) => ({
1869
+ pubkey,
1870
+ isSigner: false,
1871
+ isWritable: false
1872
+ }));
1873
+ return program.methods["crankAggregation"]().accounts({
1874
+ cranker,
1875
+ networkHealth,
1876
+ registryAccount,
1877
+ clock: CLOCK_SYSVAR
1878
+ }).remainingAccounts(remaining).instruction();
1879
+ }
1880
+ async function buildInitialize(program, authority, minStakeLamports, maxObservers) {
1881
+ const programId = program.programId;
1882
+ const [registry] = getRegistryPDA(programId);
1883
+ const [networkHealth] = getNetworkHealthPDA(programId);
1884
+ return program.methods["initialize"](
1885
+ new import_bn2.default(minStakeLamports.toString()),
1886
+ maxObservers
1887
+ ).accounts({ authority, registry, networkHealth }).instruction();
1888
+ }
1889
+ async function buildSlashObserver(program, authority, observerWallet, treasury, slashBps) {
1890
+ const programId = program.programId;
1891
+ const [observerAccount] = getObserverPDA(observerWallet, programId);
1892
+ const [registry] = getRegistryPDA(programId);
1893
+ return program.methods["slashObserver"](
1894
+ slashBps
1895
+ ).accounts({
1896
+ authority,
1897
+ observerWallet,
1898
+ observerAccount,
1899
+ registry,
1900
+ treasury
1901
+ }).instruction();
1902
+ }
1903
+ async function buildUpdateConfig(program, authority, params) {
1904
+ const programId = program.programId;
1905
+ const [registry] = getRegistryPDA(programId);
1906
+ const minStake = params.minStakeLamports != null ? new import_bn2.default(params.minStakeLamports.toString()) : null;
1907
+ return program.methods["updateConfig"](
1908
+ minStake,
1909
+ params.maxObservers,
1910
+ params.paused
1911
+ ).accounts({ authority, registry }).instruction();
1912
+ }
1913
+ async function buildProposeAuthority(program, authority, newAuthority) {
1914
+ const programId = program.programId;
1915
+ const [registry] = getRegistryPDA(programId);
1916
+ return program.methods["proposeAuthority"](
1917
+ newAuthority
1918
+ ).accounts({ authority, registry }).instruction();
1919
+ }
1920
+ async function buildAcceptAuthority(program, newAuthority) {
1921
+ const programId = program.programId;
1922
+ const [registry] = getRegistryPDA(programId);
1923
+ return program.methods["acceptAuthority"]().accounts({ newAuthority, registry }).instruction();
1924
+ }
1925
+
1926
+ // src/events.ts
1927
+ var import_web34 = require("@solana/web3.js");
1928
+ var import_bn3 = require("bn.js");
1929
+ function toBigInt2(val) {
1930
+ if (typeof val === "bigint") return val;
1931
+ if (typeof val === "number") return BigInt(val);
1932
+ return BigInt(val.toString());
1933
+ }
1934
+ function toRegion2(val) {
1935
+ const key = typeof val === "string" ? val : Object.keys(val)[0] ?? "other";
1936
+ const normalized = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
1937
+ const map = {
1938
+ Asia: "Asia",
1939
+ Us: "US",
1940
+ Eu: "EU",
1941
+ Southamerica: "SouthAmerica",
1942
+ Africa: "Africa",
1943
+ Oceania: "Oceania",
1944
+ Other: "Other"
1945
+ };
1946
+ return map[normalized] ?? "Other";
1947
+ }
1948
+ function decodeAttestationSubmitted(raw) {
1949
+ return {
1950
+ observer: raw["observer"],
1951
+ region: toRegion2(raw["region"]),
1952
+ score: raw["score"],
1953
+ reachabilityPct: raw["reachabilityPct"],
1954
+ slotLatencyMs: raw["slotLatencyMs"],
1955
+ slot: toBigInt2(raw["slot"]),
1956
+ agaveCount: raw["agaveCount"],
1957
+ firedancerCount: raw["firedancerCount"],
1958
+ jitoCount: raw["jitoCount"],
1959
+ solanaLabsCount: raw["solanaLabsCount"],
1960
+ otherCount: raw["otherCount"],
1961
+ reachableStakePct: raw["reachableStakePct"]
1962
+ };
1963
+ }
1964
+ function decodeObserverRegistered(raw) {
1965
+ return {
1966
+ observer: raw["observer"],
1967
+ region: toRegion2(raw["region"]),
1968
+ stakeLamports: toBigInt2(raw["stakeLamports"])
1969
+ };
1970
+ }
1971
+ function decodeObserverDeregistered(raw) {
1972
+ return {
1973
+ observer: raw["observer"]
1974
+ };
1975
+ }
1976
+ function decodeObserverSlashed(raw) {
1977
+ return {
1978
+ observer: raw["observer"],
1979
+ slashBps: raw["slashBps"],
1980
+ amountSlashed: toBigInt2(raw["amountSlashed"])
1981
+ };
1982
+ }
1983
+ function decodeConfigUpdated(raw) {
1984
+ const minStake = raw["minStakeLamports"];
1985
+ const maxObs = raw["maxObservers"];
1986
+ const paused = raw["paused"];
1987
+ return {
1988
+ minStakeLamports: minStake != null ? toBigInt2(minStake) : null,
1989
+ maxObservers: maxObs != null ? maxObs : null,
1990
+ paused: paused != null ? paused : null
1991
+ };
1992
+ }
1993
+
1994
+ // src/client.ts
1995
+ var READ_ONLY_PUBKEY = new import_web35.PublicKey("11111111111111111111111111111111");
1996
+ function createReadOnlyWallet() {
1997
+ return {
1998
+ publicKey: READ_ONLY_PUBKEY,
1999
+ payer: import_web35.Keypair.generate(),
2000
+ signTransaction: async (tx) => tx,
2001
+ signAllTransactions: async (txs) => txs
2002
+ };
2003
+ }
2004
+ function createS0racleClient(opts) {
2005
+ const { connection } = opts;
2006
+ const programId = opts.programId ?? PROGRAM_ID;
2007
+ const wallet = opts.wallet ?? createReadOnlyWallet();
2008
+ const provider = new import_anchor2.AnchorProvider(connection, wallet, {
2009
+ commitment: "confirmed"
2010
+ });
2011
+ const idl = { ...s0racle_program_default, address: programId.toBase58() };
2012
+ const program = new import_anchor2.Program(idl, provider);
2013
+ async function getNetworkHealth() {
2014
+ const [pda] = getNetworkHealthPDA(programId);
2015
+ const raw = await program.account["networkHealthAccount"].fetch(pda);
2016
+ return decodeNetworkHealth(raw);
2017
+ }
2018
+ async function getRegistry() {
2019
+ const [pda] = getRegistryPDA(programId);
2020
+ const raw = await program.account["registryAccount"].fetch(pda);
2021
+ return decodeRegistry(raw);
2022
+ }
2023
+ async function getObserver(observerPubkey) {
2024
+ const [pda] = getObserverPDA(observerPubkey, programId);
2025
+ const raw = await program.account["observerAccount"].fetch(pda);
2026
+ return decodeObserver(raw, pda);
2027
+ }
2028
+ async function getAllObservers() {
2029
+ const all = await program.account["observerAccount"].all();
2030
+ return all.map(
2031
+ (entry) => decodeObserver(entry.account, entry.publicKey)
2032
+ );
2033
+ }
2034
+ async function getObserversByRegion(region) {
2035
+ const all = await getAllObservers();
2036
+ return all.filter((o) => o.region === region);
2037
+ }
2038
+ return {
2039
+ programId,
2040
+ connection,
2041
+ // Reads
2042
+ getNetworkHealth,
2043
+ getRegistry,
2044
+ getObserver,
2045
+ getAllObservers,
2046
+ getObserversByRegion,
2047
+ // Instruction builders
2048
+ registerObserver: (observer, region) => buildRegisterObserver(program, observer, region),
2049
+ submitAttestation: (authority, params) => buildSubmitAttestation(program, authority, params),
2050
+ deregisterObserver: (caller, observerWallet) => buildDeregisterObserver(program, caller, observerWallet),
2051
+ crankAggregation: (cranker, observerAccounts) => buildCrankAggregation(program, cranker, observerAccounts),
2052
+ initialize: (authority, minStakeLamports, maxObservers) => buildInitialize(program, authority, minStakeLamports, maxObservers),
2053
+ slashObserver: (authority, observerWallet, treasury, slashBps) => buildSlashObserver(
2054
+ program,
2055
+ authority,
2056
+ observerWallet,
2057
+ treasury,
2058
+ slashBps
2059
+ ),
2060
+ updateConfig: (authority, params) => buildUpdateConfig(program, authority, params),
2061
+ proposeAuthority: (authority, newAuthority) => buildProposeAuthority(program, authority, newAuthority),
2062
+ acceptAuthority: (newAuthority) => buildAcceptAuthority(program, newAuthority),
2063
+ // Event subscriptions
2064
+ onAttestationSubmitted: (callback) => program.addEventListener(
2065
+ "attestationSubmitted",
2066
+ (raw, slot) => callback(
2067
+ decodeAttestationSubmitted(raw),
2068
+ slot
2069
+ )
2070
+ ),
2071
+ onObserverRegistered: (callback) => program.addEventListener(
2072
+ "observerRegistered",
2073
+ (raw, slot) => callback(
2074
+ decodeObserverRegistered(raw),
2075
+ slot
2076
+ )
2077
+ ),
2078
+ onObserverDeregistered: (callback) => program.addEventListener(
2079
+ "observerDeregistered",
2080
+ (raw, slot) => callback(
2081
+ decodeObserverDeregistered(raw),
2082
+ slot
2083
+ )
2084
+ ),
2085
+ onObserverSlashed: (callback) => program.addEventListener(
2086
+ "observerSlashed",
2087
+ (raw, slot) => callback(decodeObserverSlashed(raw), slot)
2088
+ ),
2089
+ onConfigUpdated: (callback) => program.addEventListener(
2090
+ "configUpdated",
2091
+ (raw, slot) => callback(decodeConfigUpdated(raw), slot)
2092
+ ),
2093
+ removeEventListener: (listenerId) => program.removeEventListener(listenerId)
2094
+ };
2095
+ }
2096
+
2097
+ // src/utils.ts
2098
+ var DEFAULT_DEGRADED_THRESHOLD = 70;
2099
+ var DEFAULT_CRITICAL_THRESHOLD = 40;
2100
+ function isStale(networkHealth, currentSlot) {
2101
+ return currentSlot - networkHealth.lastUpdatedSlot > STALE_SLOTS;
2102
+ }
2103
+ function isObserverStale(observer, currentSlot) {
2104
+ return currentSlot - observer.lastAttestationSlot > STALE_SLOTS;
2105
+ }
2106
+ function isDegraded(networkHealth, threshold = DEFAULT_DEGRADED_THRESHOLD) {
2107
+ return networkHealth.healthScore < threshold;
2108
+ }
2109
+ function healthStatus(networkHealth, currentSlot) {
2110
+ if (currentSlot !== void 0 && isStale(networkHealth, currentSlot)) {
2111
+ return "stale";
2112
+ }
2113
+ if (networkHealth.healthScore < DEFAULT_CRITICAL_THRESHOLD) return "critical";
2114
+ if (networkHealth.healthScore < DEFAULT_DEGRADED_THRESHOLD) return "degraded";
2115
+ return "healthy";
2116
+ }
2117
+ function regionLabel(region) {
2118
+ switch (region) {
2119
+ case "Asia" /* Asia */:
2120
+ return "Asia";
2121
+ case "US" /* US */:
2122
+ return "United States";
2123
+ case "EU" /* EU */:
2124
+ return "Europe";
2125
+ case "SouthAmerica" /* SouthAmerica */:
2126
+ return "South America";
2127
+ case "Africa" /* Africa */:
2128
+ return "Africa";
2129
+ case "Oceania" /* Oceania */:
2130
+ return "Oceania";
2131
+ case "Other" /* Other */:
2132
+ return "Other";
2133
+ }
2134
+ }
2135
+ function lamportsToSol(lamports) {
2136
+ return Number(lamports) / 1e9;
2137
+ }
2138
+ function latencyScore(slotLatencyMs) {
2139
+ if (slotLatencyMs >= 400) return 0;
2140
+ return Math.floor((400 - slotLatencyMs) * 100 / 400);
2141
+ }
2142
+ function isConsensusCritical(reachableStakePct) {
2143
+ return reachableStakePct < 67;
2144
+ }
2145
+ function stakeReachStatus(reachableStakePct) {
2146
+ if (reachableStakePct >= 80) return "healthy";
2147
+ if (reachableStakePct >= 67) return "degraded";
2148
+ return "critical";
2149
+ }
2150
+ function dominantClient(region) {
2151
+ const counts = {
2152
+ agave: region.agaveCount,
2153
+ firedancer: region.firedancerCount,
2154
+ jito: region.jitoCount,
2155
+ other: region.otherCount + region.solanaLabsCount
2156
+ };
2157
+ return Object.entries(counts).sort((a, b) => b[1] - a[1])[0][0];
2158
+ }
2159
+ function clientDiversityIndex(region) {
2160
+ const total = region.agaveCount + region.firedancerCount + region.jitoCount + region.solanaLabsCount + region.otherCount;
2161
+ if (total === 0) return 0;
2162
+ const shares = [
2163
+ region.agaveCount,
2164
+ region.firedancerCount,
2165
+ region.jitoCount,
2166
+ region.solanaLabsCount,
2167
+ region.otherCount
2168
+ ].map((c) => c / total);
2169
+ const hhi = shares.reduce((sum, s) => sum + s * s, 0);
2170
+ return Math.round((1 - hhi) * 125);
2171
+ }
2172
+ // Annotate the CommonJS export names for ESM import in node:
2173
+ 0 && (module.exports = {
2174
+ PROGRAM_ID,
2175
+ Region,
2176
+ clientDiversityIndex,
2177
+ createS0racleClient,
2178
+ dominantClient,
2179
+ getNetworkHealthPDA,
2180
+ getObserverPDA,
2181
+ getRegistryPDA,
2182
+ healthStatus,
2183
+ isConsensusCritical,
2184
+ isDegraded,
2185
+ isObserverStale,
2186
+ isStale,
2187
+ lamportsToSol,
2188
+ latencyScore,
2189
+ regionLabel,
2190
+ stakeReachStatus
2191
+ });
2192
+ //# sourceMappingURL=index.js.map