@pythnetwork/price-pusher 10.2.0 → 10.3.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.
Files changed (127) hide show
  1. package/{lib/aptos/aptos.js → dist/aptos/aptos.cjs} +80 -76
  2. package/{lib → dist}/aptos/aptos.d.ts +5 -5
  3. package/{lib/aptos/balance-tracker.js → dist/aptos/balance-tracker.cjs} +37 -25
  4. package/{lib → dist}/aptos/balance-tracker.d.ts +9 -9
  5. package/dist/aptos/command.cjs +161 -0
  6. package/{lib → dist}/aptos/command.d.ts +1 -2
  7. package/dist/common.cjs +4 -0
  8. package/{lib → dist}/common.d.ts +0 -1
  9. package/{lib/controller.js → dist/controller.cjs} +35 -33
  10. package/{lib → dist}/controller.d.ts +5 -6
  11. package/dist/evm/balance-tracker.cjs +58 -0
  12. package/{lib → dist}/evm/balance-tracker.d.ts +10 -10
  13. package/dist/evm/command.cjs +205 -0
  14. package/{lib → dist}/evm/command.d.ts +1 -2
  15. package/dist/evm/custom-gas-station.cjs +54 -0
  16. package/{lib → dist}/evm/custom-gas-station.d.ts +1 -2
  17. package/dist/evm/evm.cjs +287 -0
  18. package/{lib → dist}/evm/evm.d.ts +8 -7
  19. package/{lib/evm/pyth-abi.js → dist/evm/pyth-abi.cjs} +181 -160
  20. package/{lib → dist}/evm/pyth-abi.d.ts +0 -1
  21. package/dist/evm/pyth-contract.cjs +17 -0
  22. package/{lib → dist}/evm/pyth-contract.d.ts +3 -4
  23. package/dist/evm/super-wallet.cjs +90 -0
  24. package/{lib → dist}/evm/super-wallet.d.ts +1 -2
  25. package/dist/fuel/command.cjs +135 -0
  26. package/{lib → dist}/fuel/command.d.ts +1 -2
  27. package/dist/fuel/fuel.cjs +108 -0
  28. package/{lib → dist}/fuel/fuel.d.ts +5 -5
  29. package/dist/index.cjs +25 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/injective/command.cjs +150 -0
  32. package/{lib → dist}/injective/command.d.ts +1 -2
  33. package/{lib/injective/injective.js → dist/injective/injective.cjs} +100 -98
  34. package/{lib → dist}/injective/injective.d.ts +7 -6
  35. package/dist/interface.cjs +142 -0
  36. package/{lib → dist}/interface.d.ts +12 -13
  37. package/dist/metrics.cjs +218 -0
  38. package/{lib → dist}/metrics.d.ts +10 -11
  39. package/dist/near/command.cjs +129 -0
  40. package/{lib → dist}/near/command.d.ts +1 -2
  41. package/dist/near/near.cjs +183 -0
  42. package/{lib → dist}/near/near.d.ts +5 -5
  43. package/dist/options.cjs +132 -0
  44. package/{lib → dist}/options.d.ts +1 -2
  45. package/dist/package.json +1 -0
  46. package/dist/price-config.cjs +104 -0
  47. package/{lib → dist}/price-config.d.ts +5 -6
  48. package/{lib/pyth-price-listener.js → dist/pyth-price-listener.cjs} +30 -24
  49. package/{lib → dist}/pyth-price-listener.d.ts +4 -4
  50. package/dist/solana/balance-tracker.cjs +60 -0
  51. package/{lib → dist}/solana/balance-tracker.d.ts +9 -9
  52. package/dist/solana/command.cjs +259 -0
  53. package/{lib → dist}/solana/command.d.ts +2 -3
  54. package/{lib/solana/solana.js → dist/solana/solana.cjs} +90 -78
  55. package/{lib → dist}/solana/solana.d.ts +6 -6
  56. package/dist/sui/balance-tracker.cjs +58 -0
  57. package/{lib → dist}/sui/balance-tracker.d.ts +9 -9
  58. package/dist/sui/command.cjs +190 -0
  59. package/{lib → dist}/sui/command.d.ts +1 -2
  60. package/{lib/sui/sui.js → dist/sui/sui.cjs} +145 -133
  61. package/{lib → dist}/sui/sui.d.ts +7 -8
  62. package/dist/ton/command.cjs +137 -0
  63. package/{lib → dist}/ton/command.d.ts +1 -2
  64. package/dist/ton/ton.cjs +103 -0
  65. package/{lib → dist}/ton/ton.d.ts +7 -6
  66. package/dist/utils.cjs +102 -0
  67. package/{lib → dist}/utils.d.ts +4 -4
  68. package/package.json +161 -20
  69. package/lib/aptos/aptos.d.ts.map +0 -1
  70. package/lib/aptos/balance-tracker.d.ts.map +0 -1
  71. package/lib/aptos/command.d.ts.map +0 -1
  72. package/lib/aptos/command.js +0 -126
  73. package/lib/common.d.ts.map +0 -1
  74. package/lib/common.js +0 -2
  75. package/lib/controller.d.ts.map +0 -1
  76. package/lib/evm/balance-tracker.d.ts.map +0 -1
  77. package/lib/evm/balance-tracker.js +0 -49
  78. package/lib/evm/command.d.ts.map +0 -1
  79. package/lib/evm/command.js +0 -178
  80. package/lib/evm/custom-gas-station.d.ts.map +0 -1
  81. package/lib/evm/custom-gas-station.js +0 -40
  82. package/lib/evm/evm.d.ts.map +0 -1
  83. package/lib/evm/evm.js +0 -270
  84. package/lib/evm/pyth-abi.d.ts.map +0 -1
  85. package/lib/evm/pyth-contract.d.ts.map +0 -1
  86. package/lib/evm/pyth-contract.js +0 -11
  87. package/lib/evm/super-wallet.d.ts.map +0 -1
  88. package/lib/evm/super-wallet.js +0 -73
  89. package/lib/fuel/command.d.ts.map +0 -1
  90. package/lib/fuel/command.js +0 -98
  91. package/lib/fuel/fuel.d.ts.map +0 -1
  92. package/lib/fuel/fuel.js +0 -101
  93. package/lib/index.d.ts +0 -3
  94. package/lib/index.d.ts.map +0 -1
  95. package/lib/index.js +0 -34
  96. package/lib/injective/command.d.ts.map +0 -1
  97. package/lib/injective/command.js +0 -119
  98. package/lib/injective/injective.d.ts.map +0 -1
  99. package/lib/interface.d.ts.map +0 -1
  100. package/lib/interface.js +0 -122
  101. package/lib/metrics.d.ts.map +0 -1
  102. package/lib/metrics.js +0 -152
  103. package/lib/near/command.d.ts.map +0 -1
  104. package/lib/near/command.js +0 -103
  105. package/lib/near/near.d.ts.map +0 -1
  106. package/lib/near/near.js +0 -168
  107. package/lib/options.d.ts.map +0 -1
  108. package/lib/options.js +0 -84
  109. package/lib/price-config.d.ts.map +0 -1
  110. package/lib/price-config.js +0 -114
  111. package/lib/pyth-price-listener.d.ts.map +0 -1
  112. package/lib/solana/balance-tracker.d.ts.map +0 -1
  113. package/lib/solana/balance-tracker.js +0 -51
  114. package/lib/solana/command.d.ts.map +0 -1
  115. package/lib/solana/command.js +0 -223
  116. package/lib/solana/solana.d.ts.map +0 -1
  117. package/lib/sui/balance-tracker.d.ts.map +0 -1
  118. package/lib/sui/balance-tracker.js +0 -49
  119. package/lib/sui/command.d.ts.map +0 -1
  120. package/lib/sui/command.js +0 -160
  121. package/lib/sui/sui.d.ts.map +0 -1
  122. package/lib/ton/command.d.ts.map +0 -1
  123. package/lib/ton/command.js +0 -99
  124. package/lib/ton/ton.d.ts.map +0 -1
  125. package/lib/ton/ton.js +0 -97
  126. package/lib/utils.d.ts.map +0 -1
  127. package/lib/utils.js +0 -61
package/lib/near/near.js DELETED
@@ -1,168 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.NearAccount = exports.NearPricePusher = exports.NearPriceListener = void 0;
7
- const os_1 = __importDefault(require("os"));
8
- const path_1 = __importDefault(require("path"));
9
- const fs_1 = __importDefault(require("fs"));
10
- const interface_1 = require("../interface");
11
- const near_api_js_1 = require("near-api-js");
12
- const key_stores_1 = require("near-api-js/lib/key_stores");
13
- class NearPriceListener extends interface_1.ChainPriceListener {
14
- account;
15
- logger;
16
- constructor(account, priceItems, logger, config) {
17
- super(config.pollingFrequency, priceItems);
18
- this.account = account;
19
- this.logger = logger;
20
- }
21
- async getOnChainPriceInfo(priceId) {
22
- try {
23
- const priceRaw = await this.account.getPriceUnsafe(priceId);
24
- this.logger.debug(`Polled a NEAR on chain price for feed ${this.priceIdToAlias.get(priceId)} (${priceId}) ${JSON.stringify(priceRaw)}.`);
25
- if (priceRaw) {
26
- return {
27
- conf: priceRaw.conf,
28
- price: priceRaw.price,
29
- publishTime: priceRaw.publish_time,
30
- };
31
- }
32
- else {
33
- return undefined;
34
- }
35
- }
36
- catch (err) {
37
- this.logger.error(err, `Polling on-chain price for ${priceId} failed.:`);
38
- return undefined;
39
- }
40
- }
41
- }
42
- exports.NearPriceListener = NearPriceListener;
43
- class NearPricePusher {
44
- account;
45
- hermesClient;
46
- logger;
47
- constructor(account, hermesClient, logger) {
48
- this.account = account;
49
- this.hermesClient = hermesClient;
50
- this.logger = logger;
51
- }
52
- async updatePriceFeed(priceIds, pubTimesToPush) {
53
- if (priceIds.length === 0) {
54
- return;
55
- }
56
- if (priceIds.length !== pubTimesToPush.length)
57
- throw new Error("Invalid arguments");
58
- let priceFeedUpdateData;
59
- try {
60
- priceFeedUpdateData = await this.getPriceFeedsUpdateData(priceIds);
61
- }
62
- catch (err) {
63
- this.logger.error(err, "getPriceFeedsUpdateData failed");
64
- return;
65
- }
66
- for (const data of priceFeedUpdateData) {
67
- let updateFee;
68
- try {
69
- updateFee = await this.account.getUpdateFeeEstimate(data);
70
- this.logger.debug(`Update fee: ${updateFee}`);
71
- }
72
- catch (err) {
73
- this.logger.error(err, "getUpdateFeeEstimate failed");
74
- continue;
75
- }
76
- try {
77
- const outcome = await this.account.updatePriceFeeds(data, updateFee);
78
- const failureMessages = [];
79
- const is_success = Object.values(outcome["receipts_outcome"]).reduce((is_success, receipt) => {
80
- if (Object.prototype.hasOwnProperty.call(receipt["outcome"]["status"], "Failure")) {
81
- failureMessages.push(receipt["outcome"]["status"]);
82
- return false;
83
- }
84
- return is_success;
85
- }, true);
86
- if (is_success) {
87
- this.logger.info({ hash: outcome["transaction"]["hash"] }, "updatePriceFeeds successful.");
88
- }
89
- else {
90
- this.logger.error({ failureMessages }, "updatePriceFeeds failed");
91
- }
92
- }
93
- catch (err) {
94
- this.logger.error(err, "updatePriceFeeds failed");
95
- }
96
- }
97
- }
98
- async getPriceFeedsUpdateData(priceIds) {
99
- const response = await this.hermesClient.getLatestPriceUpdates(priceIds, {
100
- encoding: "base64",
101
- ignoreInvalidPriceIds: true,
102
- });
103
- return response.binary.data;
104
- }
105
- }
106
- exports.NearPricePusher = NearPricePusher;
107
- class NearAccount {
108
- pythAccountId;
109
- account;
110
- constructor(network, accountId, nodeUrl, privateKeyPath, pythAccountId) {
111
- this.pythAccountId = pythAccountId;
112
- const connection = this.getConnection(network, accountId, nodeUrl, privateKeyPath);
113
- this.account = new near_api_js_1.Account(connection, accountId);
114
- }
115
- async getPriceUnsafe(priceId) {
116
- return await this.account.viewFunction({
117
- contractId: this.pythAccountId,
118
- methodName: "get_price_unsafe",
119
- args: {
120
- price_identifier: priceId,
121
- },
122
- });
123
- }
124
- async getUpdateFeeEstimate(data) {
125
- return await this.account.viewFunction({
126
- contractId: this.pythAccountId,
127
- methodName: "get_update_fee_estimate",
128
- args: {
129
- data,
130
- },
131
- });
132
- }
133
- async updatePriceFeeds(data, updateFee) {
134
- return await this.account.functionCall({
135
- contractId: this.pythAccountId,
136
- methodName: "update_price_feeds",
137
- args: {
138
- data,
139
- },
140
- gas: "300000000000000",
141
- attachedDeposit: updateFee,
142
- });
143
- }
144
- getConnection(network, accountId, nodeUrl, privateKeyPath) {
145
- const content = fs_1.default.readFileSync(privateKeyPath ||
146
- path_1.default.join(os_1.default.homedir(), ".near-credentials", network, accountId + ".json"));
147
- const accountInfo = JSON.parse(content.toString());
148
- let privateKey = accountInfo.private_key;
149
- if (!privateKey && accountInfo.secret_key) {
150
- privateKey = accountInfo.secret_key;
151
- }
152
- if (accountInfo.account_id && privateKey) {
153
- const keyPair = near_api_js_1.KeyPair.fromString(privateKey);
154
- const keyStore = new key_stores_1.InMemoryKeyStore();
155
- keyStore.setKey(network, accountInfo.account_id, keyPair);
156
- return near_api_js_1.Connection.fromConfig({
157
- networkId: network,
158
- provider: { type: "JsonRpcProvider", args: { url: nodeUrl } },
159
- signer: { type: "InMemorySigner", keyStore },
160
- jsvmAccountId: `jsvm.${network}`,
161
- });
162
- }
163
- else {
164
- throw new Error("Invalid key file!");
165
- }
166
- }
167
- }
168
- exports.NearAccount = NearAccount;
@@ -1 +0,0 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,eAAO,MAAM,oBAAoB;8BAM1B,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,mBAAmB;6BAOzB,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,eAAe;yBAKrB,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,gBAAgB;yBAOtB,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,gBAAgB;yBAStB,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,YAAY;qBAKlB,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,QAAQ;iBAOd,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,kBAAkB;4BAOxB,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,aAAa;sBAMnB,OAAO;CACb,CAAC;AAEF,eAAO,MAAM,WAAW;oBAMjB,OAAO;CACb,CAAC"}
package/lib/options.js DELETED
@@ -1,84 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.metricsPort = exports.enableMetrics = exports.controllerLogLevel = exports.logLevel = exports.mnemonicFile = exports.pushingFrequency = exports.pollingFrequency = exports.priceConfigFile = exports.pythContractAddress = exports.priceServiceEndpoint = void 0;
4
- exports.priceServiceEndpoint = {
5
- "price-service-endpoint": {
6
- description: "Endpoint URL for the hermes client. e.g: https://endpoint/example",
7
- type: "string",
8
- required: true,
9
- },
10
- };
11
- exports.pythContractAddress = {
12
- "pyth-contract-address": {
13
- description: "Pyth contract address. Provide the network name on which Pyth is deployed " +
14
- "or the Pyth contract address if you use a local network.",
15
- type: "string",
16
- required: true,
17
- },
18
- };
19
- exports.priceConfigFile = {
20
- "price-config-file": {
21
- description: "Path to price configuration YAML file.",
22
- type: "string",
23
- required: true,
24
- },
25
- };
26
- exports.pollingFrequency = {
27
- "polling-frequency": {
28
- description: "The frequency to poll price info data from the network if the RPC is not a websocket.",
29
- type: "number",
30
- required: false,
31
- default: 5,
32
- },
33
- };
34
- exports.pushingFrequency = {
35
- "pushing-frequency": {
36
- description: "The frequency to push prices to the RPC. " +
37
- "It is better that the value be greater than the block time of the network, so this program confirms " +
38
- "it is updated and does not push it twice.",
39
- type: "number",
40
- required: false,
41
- default: 10,
42
- },
43
- };
44
- exports.mnemonicFile = {
45
- "mnemonic-file": {
46
- description: "Path to payer mnemonic (private key) file.",
47
- type: "string",
48
- required: true,
49
- },
50
- };
51
- exports.logLevel = {
52
- "log-level": {
53
- description: "Log level",
54
- type: "string",
55
- required: false,
56
- default: "info",
57
- choices: ["trace", "debug", "info", "warn", "error"],
58
- },
59
- };
60
- exports.controllerLogLevel = {
61
- "controller-log-level": {
62
- description: "Log level for the controller.",
63
- type: "string",
64
- required: false,
65
- default: "info",
66
- choices: ["trace", "debug", "info", "warn", "error"],
67
- },
68
- };
69
- exports.enableMetrics = {
70
- "enable-metrics": {
71
- description: "Enable Prometheus metrics server",
72
- type: "boolean",
73
- required: false,
74
- default: true,
75
- },
76
- };
77
- exports.metricsPort = {
78
- "metrics-port": {
79
- description: "Port for the Prometheus metrics server",
80
- type: "number",
81
- required: false,
82
- default: 9090,
83
- },
84
- };
@@ -1 +0,0 @@
1
- {"version":3,"file":"price-config.d.ts","sourceRoot":"","sources":["../src/price-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAIvD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAmB,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAuBxC,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,SAAS,CAAC;IACd,cAAc,EAAE,iBAAiB,CAAC;IAClC,cAAc,EAAE,SAAS,CAAC;IAC1B,eAAe,EAAE,SAAS,CAAC;IAU3B,iBAAiB,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,yBAAyB,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACzD,yBAAyB,EAAE,SAAS,GAAG,SAAS,CAAC;IACjD,0BAA0B,EAAE,SAAS,GAAG,SAAS,CAAC;CACnD,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAuB/D;AAED,oBAAY,eAAe;IAEzB,GAAG,IAAA;IAEH,KAAK,IAAA;IAEL,EAAE,IAAA;CACH;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,SAAS,GAAG,SAAS,EACxC,iBAAiB,EAAE,SAAS,GAAG,SAAS,EACxC,MAAM,EAAE,MAAM,GACb,eAAe,CAyEjB"}
@@ -1,114 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.UpdateCondition = void 0;
7
- exports.readPriceConfigFile = readPriceConfigFile;
8
- exports.shouldUpdate = shouldUpdate;
9
- const joi_1 = __importDefault(require("joi"));
10
- const yaml_1 = __importDefault(require("yaml"));
11
- const fs_1 = __importDefault(require("fs"));
12
- const utils_1 = require("./utils");
13
- const PriceConfigFileSchema = joi_1.default.array()
14
- .items(joi_1.default.object({
15
- alias: joi_1.default.string().required(),
16
- id: joi_1.default.string()
17
- .regex(/^(0x)?[a-f0-9]{64}$/)
18
- .required(),
19
- time_difference: joi_1.default.number().required(),
20
- price_deviation: joi_1.default.number().required(),
21
- confidence_ratio: joi_1.default.number().required(),
22
- early_update: joi_1.default.object({
23
- time_difference: joi_1.default.number().optional(),
24
- price_deviation: joi_1.default.number().optional(),
25
- confidence_ratio: joi_1.default.number().optional(),
26
- }).optional(),
27
- }))
28
- .unique("id")
29
- .unique("alias")
30
- .required();
31
- function readPriceConfigFile(path) {
32
- const priceConfigs = yaml_1.default.parse(fs_1.default.readFileSync(path, "utf-8"));
33
- const validationResult = PriceConfigFileSchema.validate(priceConfigs);
34
- if (validationResult.error !== undefined) {
35
- throw validationResult.error;
36
- }
37
- return priceConfigs.map((priceConfigRaw) => {
38
- const priceConfig = {
39
- alias: priceConfigRaw.alias,
40
- id: (0, utils_1.removeLeading0x)(priceConfigRaw.id),
41
- timeDifference: priceConfigRaw.time_difference,
42
- priceDeviation: priceConfigRaw.price_deviation,
43
- confidenceRatio: priceConfigRaw.confidence_ratio,
44
- customEarlyUpdate: priceConfigRaw.early_update !== undefined,
45
- earlyUpdateTimeDifference: priceConfigRaw.early_update?.time_difference,
46
- earlyUpdatePriceDeviation: priceConfigRaw.early_update?.price_deviation,
47
- earlyUpdateConfidenceRatio: priceConfigRaw.early_update?.confidence_ratio,
48
- };
49
- return priceConfig;
50
- });
51
- }
52
- var UpdateCondition;
53
- (function (UpdateCondition) {
54
- // This price feed must be updated
55
- UpdateCondition[UpdateCondition["YES"] = 0] = "YES";
56
- // This price feed may be updated as part of a larger batch
57
- UpdateCondition[UpdateCondition["EARLY"] = 1] = "EARLY";
58
- // This price feed shouldn't be updated
59
- UpdateCondition[UpdateCondition["NO"] = 2] = "NO";
60
- })(UpdateCondition || (exports.UpdateCondition = UpdateCondition = {}));
61
- /**
62
- * Checks whether on-chain price needs to be updated with the latest pyth price information.
63
- *
64
- * @param priceConfig Config of the price feed to check
65
- * @returns True if the on-chain price needs to be updated.
66
- */
67
- function shouldUpdate(priceConfig, sourceLatestPrice, targetLatestPrice, logger) {
68
- const priceId = priceConfig.id;
69
- // There is no price to update the target with. So we should not update it.
70
- if (sourceLatestPrice === undefined) {
71
- logger.info(`${priceConfig.alias} (${priceId}) is not available on the source network. Ignoring it.`);
72
- return UpdateCondition.NO;
73
- }
74
- // It means that price never existed there. So we should push the latest price feed.
75
- if (targetLatestPrice === undefined) {
76
- logger.info(`${priceConfig.alias} (${priceId}) is not available on the target network. Pushing the price.`);
77
- return UpdateCondition.YES;
78
- }
79
- // The current price is not newer than the price onchain
80
- if (sourceLatestPrice.publishTime < targetLatestPrice.publishTime) {
81
- return UpdateCondition.NO;
82
- }
83
- const timeDifference = sourceLatestPrice.publishTime - targetLatestPrice.publishTime;
84
- const priceDeviationPct = (Math.abs(Number(sourceLatestPrice.price) - Number(targetLatestPrice.price)) /
85
- Number(targetLatestPrice.price)) *
86
- 100;
87
- const confidenceRatioPct = Math.abs((Number(sourceLatestPrice.conf) / Number(sourceLatestPrice.price)) * 100);
88
- logger.info({
89
- sourcePrice: sourceLatestPrice,
90
- targetPrice: targetLatestPrice,
91
- symbol: priceConfig.alias,
92
- }, `Analyzing price ${priceConfig.alias} (${priceId}). ` +
93
- `Time difference: ${timeDifference} (< ${priceConfig.timeDifference}? / early: < ${priceConfig.earlyUpdateTimeDifference}) OR ` +
94
- `Price deviation: ${priceDeviationPct.toFixed(5)}% (< ${priceConfig.priceDeviation}%? / early: < ${priceConfig.earlyUpdatePriceDeviation}%?) OR ` +
95
- `Confidence ratio: ${confidenceRatioPct.toFixed(5)}% (< ${priceConfig.confidenceRatio}%? / early: < ${priceConfig.earlyUpdateConfidenceRatio}%?)`);
96
- if (timeDifference >= priceConfig.timeDifference ||
97
- priceDeviationPct >= priceConfig.priceDeviation ||
98
- confidenceRatioPct >= priceConfig.confidenceRatio) {
99
- return UpdateCondition.YES;
100
- }
101
- else if (priceConfig.customEarlyUpdate === undefined ||
102
- !priceConfig.customEarlyUpdate ||
103
- (priceConfig.earlyUpdateTimeDifference !== undefined &&
104
- timeDifference >= priceConfig.earlyUpdateTimeDifference) ||
105
- (priceConfig.earlyUpdatePriceDeviation !== undefined &&
106
- priceDeviationPct >= priceConfig.earlyUpdatePriceDeviation) ||
107
- (priceConfig.earlyUpdateConfidenceRatio !== undefined &&
108
- confidenceRatioPct >= priceConfig.earlyUpdateConfidenceRatio)) {
109
- return UpdateCondition.EARLY;
110
- }
111
- else {
112
- return UpdateCondition.NO;
113
- }
114
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"pyth-price-listener.d.ts","sourceRoot":"","sources":["../src/pyth-price-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EAEb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAK9B,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,mBAAmB,CAAC,CAAiB;gBAG3C,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE,MAAM;IAaV,KAAK;IAcL,cAAc;IAkDpB,kBAAkB,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS;IAI7D,OAAO;CAKR"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"balance-tracker.d.ts","sourceRoot":"","sources":["../../src/solana/balance-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAoB,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,wBAAwB;IAC1E,iCAAiC;IACjC,UAAU,EAAE,UAAU,CAAC;IACvB,wBAAwB;IACxB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,kBAAkB;IAC1D,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAY;gBAEjB,MAAM,EAAE,0BAA0B;IAU9C;;OAEG;cACa,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAwB/C;AAED;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAC/C,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,iBAAiB,CAAC;IAClC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,gCAAgC,GACvC,eAAe,CAUjB"}
@@ -1,51 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SolanaBalanceTracker = void 0;
4
- exports.createSolanaBalanceTracker = createSolanaBalanceTracker;
5
- const web3_js_1 = require("@solana/web3.js");
6
- const interface_1 = require("../interface");
7
- /**
8
- * Solana-specific implementation of the balance tracker
9
- */
10
- class SolanaBalanceTracker extends interface_1.BaseBalanceTracker {
11
- connection;
12
- publicKey;
13
- constructor(config) {
14
- super({
15
- ...config,
16
- logger: config.logger.child({ module: "SolanaBalanceTracker" }),
17
- });
18
- this.connection = config.connection;
19
- this.publicKey = config.publicKey;
20
- }
21
- /**
22
- * Solana-specific implementation of balance update
23
- */
24
- async updateBalance() {
25
- try {
26
- const balanceInLamports = await this.connection.getBalance(this.publicKey);
27
- // Convert from lamports to SOL
28
- const balanceInSol = balanceInLamports / web3_js_1.LAMPORTS_PER_SOL;
29
- this.metrics.updateWalletBalance(this.address, this.network, balanceInSol);
30
- this.logger.debug(`Updated Solana wallet balance: ${this.address} = ${balanceInSol.toString()} SOL (${balanceInLamports} lamports)`);
31
- }
32
- catch (error) {
33
- this.logger.error({ error }, "Error fetching Solana wallet balance for metrics");
34
- }
35
- }
36
- }
37
- exports.SolanaBalanceTracker = SolanaBalanceTracker;
38
- /**
39
- * Factory function to create a balance tracker for Solana
40
- */
41
- function createSolanaBalanceTracker(params) {
42
- return new SolanaBalanceTracker({
43
- connection: params.connection,
44
- publicKey: params.publicKey,
45
- address: params.publicKey.toString(),
46
- network: params.network,
47
- updateInterval: params.updateInterval,
48
- metrics: params.metrics,
49
- logger: params.logger,
50
- });
51
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/solana/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAehC,OAAO,EACL,cAAc,EAEf,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;;;;;;;;;;;;;;kBAerB,OAAO;wBAKP,OAAO;oBAKP,OAAO;6CAKP,OAAO;0BAKP,OAAO;6BAMP,OAAO;6BAKP,OAAO;6BAKP,OAAO;iCAKP,OAAO;4BAKP,OAAO;mCAKP,OAAO;wCAKP,OAAO;uBAMP,OAAO;;oBAWiB,GAAG;;AAjFpC,wBAsPE;AAEF,eAAO,MAAM,cAAc,GAAI,GAAG,cAAc,EAAE,QAAQ,MAAM,SAW/D,CAAC"}
@@ -1,223 +0,0 @@
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 () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.onBundleResult = void 0;
40
- const options = __importStar(require("../options"));
41
- const price_config_1 = require("../price-config");
42
- const pyth_price_listener_1 = require("../pyth-price-listener");
43
- const solana_1 = require("./solana");
44
- const controller_1 = require("../controller");
45
- const pyth_solana_receiver_1 = require("@pythnetwork/pyth-solana-receiver");
46
- const nodewallet_1 = __importDefault(require("@coral-xyz/anchor/dist/cjs/nodewallet"));
47
- const web3_js_1 = require("@solana/web3.js");
48
- const fs_1 = __importDefault(require("fs"));
49
- const web3_js_2 = require("@solana/web3.js");
50
- const searcher_1 = require("jito-ts/dist/sdk/block-engine/searcher");
51
- const pino_1 = __importDefault(require("pino"));
52
- const hermes_client_1 = require("@pythnetwork/hermes-client");
53
- const utils_1 = require("../utils");
54
- const metrics_1 = require("../metrics");
55
- const balance_tracker_1 = require("./balance-tracker");
56
- exports.default = {
57
- command: "solana",
58
- describe: "run price pusher for solana",
59
- builder: {
60
- endpoint: {
61
- description: "Solana RPC API endpoint",
62
- type: "string",
63
- required: true,
64
- },
65
- "keypair-file": {
66
- description: "Path to a keypair file",
67
- type: "string",
68
- required: true,
69
- },
70
- "shard-id": {
71
- description: "Shard ID",
72
- type: "number",
73
- required: true,
74
- },
75
- "compute-unit-price-micro-lamports": {
76
- description: "Priority fee per compute unit",
77
- type: "number",
78
- default: 50000,
79
- },
80
- "jito-endpoints": {
81
- description: "Jito endpoint(s) - comma-separated list of endpoints",
82
- type: "string",
83
- optional: true,
84
- },
85
- "jito-keypair-file": {
86
- description: "Path to the jito keypair file (need for grpc authentication)",
87
- type: "string",
88
- optional: true,
89
- },
90
- "jito-tip-lamports": {
91
- description: "Lamports to tip the jito builder",
92
- type: "number",
93
- optional: true,
94
- },
95
- "dynamic-jito-tips": {
96
- description: "Use dynamic jito tips",
97
- type: "boolean",
98
- default: false,
99
- },
100
- "max-jito-tip-lamports": {
101
- description: "Maximum jito tip lamports",
102
- type: "number",
103
- default: web3_js_1.LAMPORTS_PER_SOL / 100,
104
- },
105
- "jito-bundle-size": {
106
- description: "Number of transactions in each Jito bundle",
107
- type: "number",
108
- default: 5,
109
- },
110
- "updates-per-jito-bundle": {
111
- description: "Number of price updates in each Jito bundle",
112
- type: "number",
113
- default: 6,
114
- },
115
- "address-lookup-table-account": {
116
- description: "The pubkey of the ALT to use when updating price feeds",
117
- type: "string",
118
- optional: true,
119
- },
120
- "treasury-id": {
121
- description: "The treasuryId to use. Useful when the corresponding treasury account is indexed in the ALT passed to --address-lookup-table-account. This is a tx size optimization and is optional; if not set, a random treasury account will be used.",
122
- type: "number",
123
- optional: true,
124
- },
125
- ...options.priceConfigFile,
126
- ...options.priceServiceEndpoint,
127
- ...options.pythContractAddress,
128
- ...options.pollingFrequency,
129
- ...options.pushingFrequency,
130
- ...options.logLevel,
131
- ...options.controllerLogLevel,
132
- ...options.enableMetrics,
133
- ...options.metricsPort,
134
- },
135
- handler: async function (argv) {
136
- const { endpoint, keypairFile, shardId, computeUnitPriceMicroLamports, priceConfigFile, priceServiceEndpoint, pythContractAddress, pushingFrequency, pollingFrequency, jitoEndpoints, jitoKeypairFile, jitoTipLamports, dynamicJitoTips, maxJitoTipLamports, updatesPerJitoBundle, addressLookupTableAccount, treasuryId, logLevel, controllerLogLevel, enableMetrics, metricsPort, } = argv;
137
- const logger = (0, pino_1.default)({ level: logLevel });
138
- const priceConfigs = (0, price_config_1.readPriceConfigFile)(priceConfigFile);
139
- const hermesClient = new hermes_client_1.HermesClient(priceServiceEndpoint);
140
- // Initialize metrics if enabled
141
- let metrics;
142
- if (enableMetrics) {
143
- metrics = new metrics_1.PricePusherMetrics(logger.child({ module: "Metrics" }));
144
- metrics.start(metricsPort);
145
- logger.info(`Metrics server started on port ${metricsPort}`);
146
- }
147
- let priceItems = priceConfigs.map(({ id, alias }) => ({ id, alias }));
148
- // Better to filter out invalid price items before creating the pyth listener
149
- const { existingPriceItems, invalidPriceItems } = await (0, utils_1.filterInvalidPriceItems)(hermesClient, priceItems);
150
- if (invalidPriceItems.length > 0) {
151
- logger.error(`Invalid price id submitted for: ${invalidPriceItems
152
- .map(({ alias }) => alias)
153
- .join(", ")}`);
154
- }
155
- priceItems = existingPriceItems;
156
- const pythListener = new pyth_price_listener_1.PythPriceListener(hermesClient, priceItems, logger.child({ module: "PythPriceListener" }));
157
- const keypair = web3_js_1.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(fs_1.default.readFileSync(keypairFile, "ascii"))));
158
- const wallet = new nodewallet_1.default(keypair);
159
- const connection = new web3_js_1.Connection(endpoint, "processed");
160
- const pythSolanaReceiver = new pyth_solana_receiver_1.PythSolanaReceiver({
161
- connection,
162
- wallet,
163
- pushOracleProgramId: new web3_js_2.PublicKey(pythContractAddress),
164
- treasuryId: treasuryId,
165
- });
166
- // Create and start the balance tracker if metrics are enabled
167
- if (metrics) {
168
- const balanceTracker = (0, balance_tracker_1.createSolanaBalanceTracker)({
169
- connection,
170
- publicKey: keypair.publicKey,
171
- network: "solana",
172
- updateInterval: 60,
173
- metrics,
174
- logger,
175
- });
176
- // Start the balance tracker
177
- await balanceTracker.start();
178
- }
179
- // Fetch the account lookup table if provided
180
- const lookupTableAccount = addressLookupTableAccount
181
- ? await connection
182
- .getAddressLookupTable(new web3_js_2.PublicKey(addressLookupTableAccount))
183
- .then((result) => result.value ?? undefined)
184
- : undefined;
185
- let solanaPricePusher;
186
- if (jitoTipLamports) {
187
- const jitoKeypair = web3_js_1.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(fs_1.default.readFileSync(jitoKeypairFile, "ascii"))));
188
- const jitoEndpointsList = jitoEndpoints
189
- .split(",")
190
- .map((endpoint) => endpoint.trim());
191
- const jitoClients = jitoEndpointsList.map((endpoint) => {
192
- logger.info(`Constructing Jito searcher client from endpoint ${endpoint}`);
193
- return (0, searcher_1.searcherClient)(endpoint, jitoKeypair);
194
- });
195
- solanaPricePusher = new solana_1.SolanaPricePusherJito(pythSolanaReceiver, hermesClient, logger.child({ module: "SolanaPricePusherJito" }), shardId, jitoTipLamports, dynamicJitoTips, maxJitoTipLamports, jitoClients, updatesPerJitoBundle,
196
- // Set max retry time to pushing frequency, since we want to stop retrying before the next push attempt
197
- pushingFrequency * 1000, lookupTableAccount);
198
- jitoClients.forEach((client, index) => {
199
- (0, exports.onBundleResult)(client, logger.child({ module: `JitoClient-${index}` }));
200
- });
201
- }
202
- else {
203
- solanaPricePusher = new solana_1.SolanaPricePusher(pythSolanaReceiver, hermesClient, logger.child({ module: "SolanaPricePusher" }), shardId, computeUnitPriceMicroLamports, lookupTableAccount);
204
- }
205
- const solanaPriceListener = new solana_1.SolanaPriceListener(pythSolanaReceiver, shardId, priceItems, logger.child({ module: "SolanaPriceListener" }), { pollingFrequency });
206
- const controller = new controller_1.Controller(priceConfigs, pythListener, solanaPriceListener, solanaPricePusher, logger.child({ module: "Controller" }, { level: controllerLogLevel }), {
207
- pushingFrequency,
208
- metrics,
209
- });
210
- controller.start();
211
- },
212
- };
213
- const onBundleResult = (c, logger) => {
214
- try {
215
- c.onBundleResult(() => undefined, (err) => {
216
- logger.error(err, "Error in bundle result");
217
- });
218
- }
219
- catch (error) {
220
- logger.error(error, "Exception in bundle result");
221
- }
222
- };
223
- exports.onBundleResult = onBundleResult;
@@ -1 +0,0 @@
1
- {"version":3,"file":"solana.d.ts","sourceRoot":"","sources":["../../src/solana/solana.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAK1D,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAExE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,yBAAyB,EAAoB,MAAM,iBAAiB,CAAC;AAI9E,qBAAa,mBAAoB,SAAQ,kBAAkB;IAEvD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,OAAO;IAEf,OAAO,CAAC,MAAM;gBAHN,kBAAkB,EAAE,kBAAkB,EACtC,OAAO,EAAE,MAAM,EACvB,UAAU,EAAE,SAAS,EAAE,EACf,MAAM,EAAE,MAAM,EACtB,MAAM,EAAE;QACN,gBAAgB,EAAE,iBAAiB,CAAC;KACrC;YAOW,WAAW;IAsBnB,KAAK;IAOL,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CA0B3E;AAED,qBAAa,iBAAkB,YAAW,YAAY;IAElD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,6BAA6B;IACrC,OAAO,CAAC,yBAAyB,CAAC;gBAL1B,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,6BAA6B,EAAE,MAAM,EACrC,yBAAyB,CAAC,EAAE,yBAAyB,YAAA;IAGzD,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAuDzD;AAED,qBAAa,qBAAsB,YAAW,YAAY;IAEtD,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,sBAAsB;IAC9B,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,oBAAoB;IAC5B,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,yBAAyB,CAAC;gBAV1B,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,eAAe,EAAE,OAAO,EACxB,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,cAAc,EAAE,EACjC,oBAAoB,EAAE,MAAM,EAC5B,cAAc,EAAE,MAAM,EACtB,yBAAyB,CAAC,EAAE,yBAAyB,YAAA;IAGzD,wBAAwB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAsBvD,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAuDzD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"balance-tracker.d.ts","sourceRoot":"","sources":["../../src/sui/balance-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,wBAAwB;IACvE,0BAA0B;IAC1B,MAAM,EAAE,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,kBAAkB;IACvD,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,EAAE,uBAAuB;IAS3C;;OAEG;cACa,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAyB/C;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,iBAAiB,CAAC;IAClC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,6BAA6B,GACpC,eAAe,CASjB"}