From 5918dac7f3cbf076419d9158212964394079e4f6 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Tue, 25 Jun 2024 12:18:53 +0200 Subject: [PATCH 01/40] decoding for on demand oracles Signed-off-by: microwavedcola1 --- yarn.lock | 520 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 515 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0f420b723..3af37ed3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,6 +30,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== + dependencies: + regenerator-runtime "^0.14.0" + "@blockworks-foundation/mango-v4-settings@0.14.15": version "0.14.15" resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.14.15.tgz#0ac04f2cffbd27a4129bc2086ec1418e29393880" @@ -54,7 +61,12 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@coral-xyz/anchor@^0.26.0", "@coral-xyz/anchor@^0.28.1-beta.2": +"@coral-xyz/anchor-errors@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor-errors/-/anchor-errors-0.30.1.tgz#bdfd3a353131345244546876eb4afc0e125bec30" + integrity sha512-9Mkradf5yS5xiLWrl9WrpjqOrAV+/W2RQHDlbnAZBivoGpOs1ECjoDCkVk4aRG8ZdiFiB8zQEVlxf+8fKkmSfQ== + +"@coral-xyz/anchor@^0.26.0", "@coral-xyz/anchor@^0.28.1-beta.2", "@coral-xyz/anchor@^0.30.0": version "0.28.1-beta.2" resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.28.1-beta.2.tgz#4ddd4b2b66af04407be47cf9524147793ec514a0" integrity sha512-xreUcOFF8+IQKWOBUrDKJbIw2ftpRVybFlEPVrbSlOBCbreCWrQ5754Gt9cHIcuBDAzearCDiBqzsGQdNgPJiw== @@ -75,6 +87,27 @@ superstruct "^0.15.4" toml "^3.0.0" +"@coral-xyz/anchor@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.1.tgz#17f3e9134c28cd0ea83574c6bab4e410bcecec5d" + integrity sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ== + dependencies: + "@coral-xyz/anchor-errors" "^0.30.1" + "@coral-xyz/borsh" "^0.30.1" + "@noble/hashes" "^1.3.1" + "@solana/web3.js" "^1.68.0" + bn.js "^5.1.2" + bs58 "^4.0.1" + buffer-layout "^1.2.2" + camelcase "^6.3.0" + cross-fetch "^3.1.5" + crypto-hash "^1.3.0" + eventemitter3 "^4.0.7" + pako "^2.0.3" + snake-case "^3.0.4" + superstruct "^0.15.4" + toml "^3.0.0" + "@coral-xyz/borsh@^0.28.0": version "0.28.0" resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.28.0.tgz#fa368a2f2475bbf6f828f4657f40a52102e02b6d" @@ -83,6 +116,14 @@ bn.js "^5.1.2" buffer-layout "^1.2.0" +"@coral-xyz/borsh@^0.30.1": + version "0.30.1" + resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.30.1.tgz#869d8833abe65685c72e9199b8688477a4f6b0e3" + integrity sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ== + dependencies: + bn.js "^5.1.2" + buffer-layout "^1.2.0" + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -169,11 +210,23 @@ dependencies: "@noble/hashes" "1.3.3" +"@noble/curves@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" + integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== + dependencies: + "@noble/hashes" "1.4.0" + "@noble/hashes@1.3.3", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.2": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== +"@noble/hashes@1.4.0", "@noble/hashes@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -254,6 +307,59 @@ bn.js "^5.1.2" buffer-layout "^1.2.0" +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@pythnetwork/client@~2.14.0": version "2.14.0" resolved "https://registry.yarnpkg.com/@pythnetwork/client/-/client-2.14.0.tgz#0c12a7e1bcc66ff198fdb64c003b8d4a24431efc" @@ -279,6 +385,66 @@ dependencies: buffer "~6.0.3" +"@solana/codecs-core@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.0.0-preview.2.tgz#689784d032fbc1fedbde40bb25d76cdcecf6553b" + integrity sha512-gLhCJXieSCrAU7acUJjbXl+IbGnqovvxQLlimztPoGgfLQ1wFYu+XJswrEVQqknZYK1pgxpxH3rZ+OKFs0ndQg== + dependencies: + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs-data-structures@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-preview.2.tgz#e82cb1b6d154fa636cd5c8953ff3f32959cc0370" + integrity sha512-Xf5vIfromOZo94Q8HbR04TbgTwzigqrKII0GjYr21K7rb3nba4hUW2ir8kguY7HWFBcjHGlU5x3MevKBOLp3Zg== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs-numbers@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-preview.2.tgz#56995c27396cd8ee3bae8bd055363891b630bbd0" + integrity sha512-aLZnDTf43z4qOnpTcDsUVy1Ci9im1Md8thWipSWbE+WM9ojZAx528oAql+Cv8M8N+6ALKwgVRhPZkto6E59ARw== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs-strings@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-2.0.0-preview.2.tgz#8bd01a4e48614d5289d72d743c3e81305d445c46" + integrity sha512-EgBwY+lIaHHgMJIqVOGHfIfpdmmUDNoNO/GAUGeFPf+q0dF+DtwhJPEMShhzh64X2MeCZcmSO6Kinx0Bvmmz2g== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + "@solana/errors" "2.0.0-preview.2" + +"@solana/codecs@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/codecs/-/codecs-2.0.0-preview.2.tgz#d6615fec98f423166fb89409f9a4ad5b74c10935" + integrity sha512-4HHzCD5+pOSmSB71X6w9ptweV48Zj1Vqhe732+pcAQ2cMNnN0gMPMdDq7j3YwaZDZ7yrILVV/3+HTnfT77t2yA== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-data-structures" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + "@solana/codecs-strings" "2.0.0-preview.2" + "@solana/options" "2.0.0-preview.2" + +"@solana/errors@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.0.0-preview.2.tgz#e0ea8b008c5c02528d5855bc1903e5e9bbec322e" + integrity sha512-H2DZ1l3iYF5Rp5pPbJpmmtCauWeQXRJapkDg8epQ8BJ7cA2Ut/QEtC3CMmw/iMTcuS6uemFNLcWvlOfoQhvQuA== + dependencies: + chalk "^5.3.0" + commander "^12.0.0" + +"@solana/options@2.0.0-preview.2": + version "2.0.0-preview.2" + resolved "https://registry.yarnpkg.com/@solana/options/-/options-2.0.0-preview.2.tgz#13ff008bf43a5056ef9a091dc7bb3f39321e867e" + integrity sha512-FAHqEeH0cVsUOTzjl5OfUBw2cyT8d5Oekx4xcn5hn+NyPAfQJgM3CEThzgRD6Q/4mM5pVUnND3oK/Mt1RzSE/w== + dependencies: + "@solana/codecs-core" "2.0.0-preview.2" + "@solana/codecs-numbers" "2.0.0-preview.2" + "@solana/spl-governance@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@solana/spl-governance/-/spl-governance-0.3.25.tgz#57563003ebd4cf0bf778876035828196e34e29fd" @@ -292,6 +458,22 @@ bs58 "^4.0.1" superstruct "^0.15.2" +"@solana/spl-token-group@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.4.tgz#4f45d9526c96a33b9a1929a264d0aa21c7e38a2d" + integrity sha512-7+80nrEMdUKlK37V6kOe024+T7J4nNss0F8LQ9OOPYdWCCfJmsGUzVx2W3oeizZR4IHM6N4yC9v1Xqwc3BTPWw== + dependencies: + "@solana/codecs" "2.0.0-preview.2" + "@solana/spl-type-length-value" "0.1.0" + +"@solana/spl-token-metadata@^0.1.2", "@solana/spl-token-metadata@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.4.tgz#5cdc3b857a8c4a6877df24e24a8648c4132d22ba" + integrity sha512-N3gZ8DlW6NWDV28+vCCDJoTqaCZiF/jDUnk3o8GRkAFzHObiR60Bs1gXHBa8zCPdvOwiG6Z3dg5pg7+RW6XNsQ== + dependencies: + "@solana/codecs" "2.0.0-preview.2" + "@solana/spl-type-length-value" "0.1.0" + "@solana/spl-token@0.3.7": version "0.3.7" resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.7.tgz#6f027f9ad8e841f792c32e50920d9d2e714fc8da" @@ -313,6 +495,34 @@ buffer-layout "^1.2.0" dotenv "10.0.0" +"@solana/spl-token@^0.3.4": + version "0.3.11" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" + integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + "@solana/spl-token-metadata" "^0.1.2" + buffer "^6.0.3" + +"@solana/spl-token@^0.4.1": + version "0.4.6" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.4.6.tgz#eb44e5080ea7b6fc976abcb39457223211bd9076" + integrity sha512-1nCnUqfHVtdguFciVWaY/RKcQz1IF4b31jnKgAmjU9QVN1q7dRUkTEWJZgTYIEtsULjVnC9jRqlhgGN39WbKKA== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + "@solana/spl-token-group" "^0.0.4" + "@solana/spl-token-metadata" "^0.1.4" + buffer "^6.0.3" + +"@solana/spl-type-length-value@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz#b5930cf6c6d8f50c7ff2a70463728a4637a2f26b" + integrity sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA== + dependencies: + buffer "^6.0.3" + "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.78.2", "@solana/web3.js@^1.88.0": version "1.88.0" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.88.0.tgz#24e1482f63ac54914430b4ce5ab36eaf433ecdb8" @@ -334,6 +544,84 @@ rpc-websockets "^7.5.1" superstruct "^0.14.2" +"@solana/web3.js@^1.54.0", "@solana/web3.js@^1.91.1", "@solana/web3.js@^1.93.0": + version "1.93.1" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.93.1.tgz#7e1c0132b539f6515166760ebbeda0a4375f0fe3" + integrity sha512-3TzngqyzukYbuuweL1ejJJEPXmSRoOjaUsfBcfdx9RyDZtyP9av/GerV52mF6Lj2zEVkE7ZczpEP4tKJ8anxVQ== + dependencies: + "@babel/runtime" "^7.24.7" + "@noble/curves" "^1.4.0" + "@noble/hashes" "^1.4.0" + "@solana/buffer-layout" "^4.0.1" + agentkeepalive "^4.5.0" + bigint-buffer "^1.1.5" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.0" + node-fetch "^2.7.0" + rpc-websockets "^9.0.2" + superstruct "^1.0.4" + +"@solworks/soltoolkit-sdk@^0.0.23": + version "0.0.23" + resolved "https://registry.yarnpkg.com/@solworks/soltoolkit-sdk/-/soltoolkit-sdk-0.0.23.tgz#ef32d0aa79f888bcf0f639d280005b2e97cdc624" + integrity sha512-O6lXT3EBR4gmcjt0/33i97VMHVEImwXGi+4TNrDDdifn3tyOUB7V6PR1VGxlavQb9hqmVai3xhedg/rmbQzX7w== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/spl-token" "^0.3.4" + "@solana/web3.js" "^1.54.0" + "@types/bn.js" "^5.1.0" + "@types/node" "^18.7.13" + "@types/node-fetch" "^2.6.2" + bn.js "^5.2.1" + decimal.js "^10.4.0" + typescript "^4.8.2" + +"@swc/helpers@^0.5.11": + version "0.5.11" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.11.tgz#5bab8c660a6e23c13b2d23fcd1ee44a2db1b0cb7" + integrity sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A== + dependencies: + tslib "^2.4.0" + +"@switchboard-xyz/common@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/common/-/common-2.4.2.tgz#cf48561a48d937bbf33bfa5736c4d8b55ea56d3d" + integrity sha512-J04t/urufpyLcUU2C10n0hFCCW0OrghkUc2NXvYjw5BPHDG76Y9gMrrcSPM/6e+VjfverVOUAsiepLHJnAV+cA== + dependencies: + "@solana/web3.js" "^1.93.0" + axios "^1.7.2" + big.js "^6.2.1" + bn.js "^5.2.1" + bs58 "^5.0.0" + cron-validator "^1.3.1" + decimal.js "^10.4.3" + form-data "^4.0.0" + lodash "^4.17.21" + protobufjs "^7.2.6" + yaml "^2.2.1" + +"@switchboard-xyz/on-demand@^1.1.24": + version "1.1.24" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.1.24.tgz#7cf9bdcd1ac30ad4de6ab0286a84fcdbd02ff374" + integrity sha512-IFqwO7j3JsJ9qWPV0oc4hr/4DVavGaBoLWIB132Uf8NLQleIsij8ay36QHeZ+StJurv9NNUbUhzfPrXo6QwYYw== + dependencies: + "@coral-xyz/anchor" "^0.30.0" + "@solana/spl-token" "^0.4.1" + "@solana/web3.js" "^1.91.1" + "@solworks/soltoolkit-sdk" "^0.0.23" + "@switchboard-xyz/common" "^2.4.2" + axios "^1.2.0" + big.js "^6.2.1" + bs58 "^5.0.0" + js-yaml "^4.1.0" + node-cache "^5.1.2" + protobufjs "^7.2.6" + shelljs "^0.8.5" + "@switchboard-xyz/sbv2-lite@^0.1.6": version "0.1.6" resolved "https://registry.yarnpkg.com/@switchboard-xyz/sbv2-lite/-/sbv2-lite-0.1.6.tgz#dc3fbb5b3b028dbd3c688b991bcc48a670131ddb" @@ -374,6 +662,13 @@ dependencies: "@types/node" "*" +"@types/bn.js@^5.1.0": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== + dependencies: + "@types/node" "*" + "@types/bn.js@^5.1.1": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" @@ -415,11 +710,26 @@ resolved "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz" integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== +"@types/node-fetch@^2.6.2": + version "2.6.11" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" + integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g== + dependencies: + "@types/node" "*" + form-data "^4.0.0" + "@types/node@*": version "20.5.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.0.tgz#7fc8636d5f1aaa3b21e6245e97d56b7f56702313" integrity sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q== +"@types/node@>=13.7.0": + version "20.14.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.8.tgz#45c26a2a5de26c3534a9504530ddb3b27ce031ac" + integrity sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA== + dependencies: + undici-types "~5.26.4" + "@types/node@^12.12.54": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" @@ -435,6 +745,18 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== +"@types/node@^18.7.13": + version "18.19.39" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.39.tgz#c316340a5b4adca3aee9dcbf05de385978590593" + integrity sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ== + dependencies: + undici-types "~5.26.4" + +"@types/uuid@^8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + "@types/ws@^7.4.4": version "7.4.7" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" @@ -442,6 +764,13 @@ dependencies: "@types/node" "*" +"@types/ws@^8.2.2": + version "8.5.10" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== + dependencies: + "@types/node" "*" + "@typescript-eslint/eslint-plugin@^5.32.0": version "5.32.0" resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.32.0.tgz" @@ -672,6 +1001,15 @@ axios@^1.1.3, axios@^1.4.0: form-data "^4.0.0" proxy-from-env "^1.1.0" +axios@^1.2.0, axios@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" @@ -694,7 +1032,7 @@ base64-js@^1.3.1, base64-js@^1.5.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -big.js@^6.1.1: +big.js@^6.1.1, big.js@^6.2.1: version "6.2.1" resolved "https://registry.npmjs.org/big.js/-/big.js-6.2.1.tgz" integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== @@ -874,6 +1212,11 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + check-error@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" @@ -912,6 +1255,11 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +clone@2.x: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" @@ -943,6 +1291,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@^12.0.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -970,6 +1323,11 @@ create-require@^1.1.0: resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cron-validator@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.3.1.tgz#8f2fe430f92140df77f91178ae31fc1e3a48a20e" + integrity sha512-C1HsxuPCY/5opR55G5/WNzyEGDWFVG+6GLrA+fW/sCTcP6A6NTjUP2AK7B8n2PyFs90kDG2qzwm8LMheADku6A== + cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" @@ -1010,6 +1368,11 @@ decamelize@^4.0.0: resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decimal.js@^10.4.0, decimal.js@^10.4.3: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + deep-eql@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" @@ -1272,6 +1635,11 @@ eventemitter3@^4.0.7: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + eyes@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" @@ -1385,6 +1753,11 @@ follow-redirects@^1.15.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -1404,6 +1777,11 @@ fsevents@~2.3.2: resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" @@ -1438,6 +1816,18 @@ glob@7.2.0, glob@^7.1.3, glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.0.0: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^13.6.0, globals@^13.9.0: version "13.12.1" resolved "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz" @@ -1480,6 +1870,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" @@ -1550,6 +1947,11 @@ inherits@2, inherits@^2.0.3, inherits@^2.0.4: resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" @@ -1557,6 +1959,13 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-core-module@^2.13.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== + dependencies: + hasown "^2.0.2" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" @@ -1645,7 +2054,7 @@ js-tokens@^4.0.0: resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@4.1.0: +js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -1787,6 +2196,11 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +long@^5.0.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + loupe@^2.3.1: version "2.3.4" resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz" @@ -1865,7 +2279,7 @@ minimatch@4.2.1: dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.4: +minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -1947,6 +2361,13 @@ node-addon-api@^5.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== +node-cache@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" + integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg== + dependencies: + clone "2.x" + node-fetch@2.6.11, node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.7.0, "node-fetch@npm:@blockworks-foundation/node-fetch@2.6.11": version "2.6.11" resolved "https://registry.yarnpkg.com/@blockworks-foundation/node-fetch/-/node-fetch-2.6.11.tgz#fb536ef0e6a960e7b7993f3c1d3b3bba9bdfbc56" @@ -2036,6 +2457,11 @@ path-key@^3.1.0: resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" @@ -2066,6 +2492,24 @@ progress@^2.0.0: resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== +protobufjs@^7.2.6: + version "7.3.2" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.3.2.tgz#60f3b7624968868f6f739430cfbc8c9370e26df4" + integrity sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -2095,6 +2539,13 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== + dependencies: + resolve "^1.1.6" + reconnecting-websocket@^4.2.0: version "4.4.0" resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783" @@ -2125,6 +2576,15 @@ resolve-from@^4.0.0: resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve@^1.1.6: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" @@ -2150,6 +2610,22 @@ rpc-websockets@^7.5.1: bufferutil "^4.0.1" utf-8-validate "^5.0.2" +rpc-websockets@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.0.2.tgz#4c1568d00b8100f997379a363478f41f8f4b242c" + integrity sha512-YzggvfItxMY3Lwuax5rC18inhbjJv9Py7JXRHxTIi94JOLrqBsSsUUc5bbl5W6c11tXhdfpDPK0KzBhoGe8jjw== + dependencies: + "@swc/helpers" "^0.5.11" + "@types/uuid" "^8.3.4" + "@types/ws" "^8.2.2" + buffer "^6.0.3" + eventemitter3 "^5.0.1" + uuid "^8.3.2" + ws "^8.5.0" + optionalDependencies: + bufferutil "^4.0.1" + utf-8-validate "^5.0.2" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" @@ -2197,6 +2673,15 @@ shebang-regex@^3.0.0: resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shelljs@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + shiki@^0.10.0: version "0.10.1" resolved "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz" @@ -2287,6 +2772,11 @@ superstruct@^0.15.2, superstruct@^0.15.4: resolved "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz" integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== +superstruct@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== + supports-color@8.1.1: version "8.1.1" resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" @@ -2308,6 +2798,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + table@^6.0.9: version "6.8.0" resolved "https://registry.npmjs.org/table/-/table-6.8.0.tgz" @@ -2423,6 +2918,11 @@ tslib@^2.0.3: resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.4.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" @@ -2463,11 +2963,16 @@ typedoc@^0.22.5: minimatch "^3.0.4" shiki "^0.10.0" -typescript@^4.8.4: +typescript@^4.8.2, typescript@^4.8.4: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" @@ -2576,6 +3081,11 @@ yallist@^4.0.0: resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^2.2.1: + version "2.4.5" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" + integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" From 989600263bd01c7fb26e613f16365eb96e891bbc Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Tue, 25 Jun 2024 14:01:48 +0200 Subject: [PATCH 02/40] update Signed-off-by: microwavedcola1 --- package.json | 3 +- .../scripts/archive/mb-oracle-inspect.ts | 35 +++++++--- ts/client/scripts/sb-on-demand-crank.ts | 18 +++++ ts/client/src/accounts/oracle.ts | 67 ++++++++++++++++--- 4 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 ts/client/scripts/sb-on-demand-crank.ts diff --git a/package.json b/package.json index e1d1492bd..760e3582d 100644 --- a/package.json +++ b/package.json @@ -64,11 +64,12 @@ "dependencies": { "@blockworks-foundation/mango-v4-settings": "0.14.15", "@blockworks-foundation/mangolana": "0.0.14", - "@coral-xyz/anchor": "^0.28.1-beta.2", + "@coral-xyz/anchor": "^0.30.1", "@project-serum/serum": "0.13.65", "@pythnetwork/client": "~2.14.0", "@solana/spl-token": "0.3.7", "@solana/web3.js": "^1.78.2", + "@switchboard-xyz/on-demand": "^1.1.24", "@switchboard-xyz/sbv2-lite": "^0.1.6", "big.js": "^6.1.1", "binance-api-node": "^0.12.0", diff --git a/ts/client/scripts/archive/mb-oracle-inspect.ts b/ts/client/scripts/archive/mb-oracle-inspect.ts index 452272441..51e41c08f 100644 --- a/ts/client/scripts/archive/mb-oracle-inspect.ts +++ b/ts/client/scripts/archive/mb-oracle-inspect.ts @@ -31,17 +31,30 @@ async function decodePrice(conn, ai, pk): Promise { async function main(): Promise { try { - const oraclePk1 = new PublicKey( - '4SZ1qb4MtSUrZcoeaeQ3BDzVCyqxw3VwSFpPiMTmn4GE', - ); - const conn = new Connection(MB_CLUSTER_URL!); - let ai = await conn.getAccountInfo(oraclePk1); - decodePrice(conn, ai, oraclePk1); - const oraclePk2 = new PublicKey( - '8ihFLu5FimgTQ1Unh4dVyEHUGodJ5gJQCrQf4KUVB9bN', - ); - ai = await conn.getAccountInfo(oraclePk2); - decodePrice(conn, ai, oraclePk2); + // { + // const oraclePk1 = new PublicKey( + // '4SZ1qb4MtSUrZcoeaeQ3BDzVCyqxw3VwSFpPiMTmn4GE', + // ); + // const conn = new Connection(MB_CLUSTER_URL!); + // let ai = await conn.getAccountInfo(oraclePk1); + // decodePrice(conn, ai, oraclePk1); + + // const oraclePk2 = new PublicKey( + // '8ihFLu5FimgTQ1Unh4dVyEHUGodJ5gJQCrQf4KUVB9bN', + // ); + // ai = await conn.getAccountInfo(oraclePk2); + // decodePrice(conn, ai, oraclePk2); + // } + + { + // https://ondemand.switchboard.xyz/solana/devnet/feed/23QLa7R2hDhcXDVKyUSt2rvBPtuAAbY44TrqMVoPpk1C + const oraclePk3 = new PublicKey( + 'EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf', + ); + const devnetConn = new Connection(process.env.DEVNET_CLUSTER_URL!); + const ai = await devnetConn.getAccountInfo(oraclePk3); + decodePrice(devnetConn, ai, oraclePk3); + } } catch (error) { console.log(error); } diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts new file mode 100644 index 000000000..ba5c33acd --- /dev/null +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -0,0 +1,18 @@ +(async function main() { + + + // get all oracles to crank + // maybe support more than one mango group + // maybe support additional via csv env param + + + // loop indefinitely + + // filter candidates for this iteration + + // build pullix for each + + // batch them + + +}); diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index 3c91f9a1e..dded3d208 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -1,5 +1,7 @@ +import { AnchorProvider, Program, Wallet } from '@coral-xyz/anchor'; import { Magic as PythMagic } from '@pythnetwork/client'; -import { AccountInfo, Connection, PublicKey } from '@solana/web3.js'; +import { AccountInfo, Connection, Keypair, PublicKey } from '@solana/web3.js'; +import { SB_ON_DEMAND_PID } from '@switchboard-xyz/on-demand'; import SwitchboardProgram from '@switchboard-xyz/sbv2-lite'; import Big from 'big.js'; import BN from 'bn.js'; @@ -13,6 +15,7 @@ const SBV1_MAINNET_PID = new PublicKey( ); let sbv2DevnetProgram; let sbv2MainnetProgram; +let sbOnDemandProgram; export enum OracleProvider { Pyth, @@ -106,24 +109,69 @@ export function parseSwitchboardOracleV2( ); return { price, lastUpdatedSlot, uiDeviation: stdDeviation.toNumber() }; - //if oracle is badly configured or didn't publish price at least once - //decodeLatestAggregatorValue can throw (0 switchboard rounds). + // if oracle is badly configured or didn't publish price at least once + // decodeLatestAggregatorValue can throw (0 switchboard rounds). } catch (e) { console.log(`Unable to parse Switchboard Oracle V2: ${oracle}`, e); return { price: 0, lastUpdatedSlot: 0, uiDeviation: 0 }; } } -/** - * - * @param accountInfo - * @returns ui price - */ +export function parseSwitchboardOnDemandOracle( + program: any, + accountInfo: AccountInfo, + oracle: PublicKey, +): { price: number; lastUpdatedSlot: number; uiDeviation: number } { + try { + const decodedPullFeed = program.coder.accounts.decode( + 'pullFeedAccountData', + accountInfo.data, + ); + + // This code was used when decodedPullFeed.result used to be empty + // const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); + // const price = new Big(feedValue?.value.toString()).div(1e18); + // const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! + // const stdDeviation = 0; // TODO the 0 + + const price = new Big(decodedPullFeed.result.value.toString()).div(1e18); + const lastUpdatedSlot = decodedPullFeed.result.slot.toNumber(); + const stdDeviation = decodedPullFeed.result.stdDev.toNumber(); + + return { price, lastUpdatedSlot, uiDeviation: stdDeviation }; + } catch (e) { + console.log( + `Unable to parse Switchboard On-Demand Oracle V2: ${oracle}`, + e, + ); + return { price: 0, lastUpdatedSlot: 0, uiDeviation: 0 }; + } +} + export async function parseSwitchboardOracle( oracle: PublicKey, accountInfo: AccountInfo, connection: Connection, ): Promise<{ price: number; lastUpdatedSlot: number; uiDeviation: number }> { + if (accountInfo.owner.equals(SB_ON_DEMAND_PID)) { + if (!sbOnDemandProgram) { + const options = AnchorProvider.defaultOptions(); + const provider = new AnchorProvider( + connection, + new Wallet(new Keypair()), + options, + ); + const idl = await Program.fetchIdl(SB_ON_DEMAND_PID, provider); + // console.log(idl); + sbOnDemandProgram = new Program(idl!, provider); + } + return parseSwitchboardOnDemandOracle( + sbOnDemandProgram, + accountInfo, + oracle, + ); + } + if (accountInfo.owner.equals(SwitchboardProgram.devnetPid)) { if (!sbv2DevnetProgram) { sbv2DevnetProgram = await SwitchboardProgram.loadDevnet(connection); @@ -153,7 +201,8 @@ export function isSwitchboardOracle(accountInfo: AccountInfo): boolean { accountInfo.owner.equals(SBV1_DEVNET_PID) || accountInfo.owner.equals(SBV1_MAINNET_PID) || accountInfo.owner.equals(SwitchboardProgram.devnetPid) || - accountInfo.owner.equals(SwitchboardProgram.mainnetPid) + accountInfo.owner.equals(SwitchboardProgram.mainnetPid) || + accountInfo.owner.equals(SB_ON_DEMAND_PID) ) { return true; } From ee3049627036399a8869750166f6f5973f78922a Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Tue, 25 Jun 2024 15:14:34 +0200 Subject: [PATCH 03/40] add draft of crank Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 230 +++++++++++++++++++++++- 1 file changed, 222 insertions(+), 8 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index ba5c33acd..4855aa4d7 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -1,18 +1,232 @@ +import { AnchorProvider, Program, Wallet } from '@coral-xyz/anchor'; +import { + AccountInfo, + Cluster, + Commitment, + Connection, + Keypair, + PublicKey, + TransactionInstruction, +} from '@solana/web3.js'; +import { + asV0Tx, + loadLookupTables, + Oracle, + PullFeed, + SB_ON_DEMAND_PID, +} from '@switchboard-xyz/on-demand'; +import chunk from 'lodash/chunk'; +import intersection from 'lodash/intersection'; +import { OracleConfig } from '../src/accounts/bank'; +import { parseSwitchboardOracle } from '../src/accounts/oracle'; +import { MangoClient } from '../src/client'; +import { MANGO_V4_ID } from '../src/constants'; +import { ZERO_I80F48 } from '../src/numbers/I80F48'; + +const CLUSTER: Cluster = + (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; +const CLUSTER_URL = + process.env.CLUSTER_URL_OVERRIDE || process.env.MB_CLUSTER_URL; +const USER_KEYPAIR = + process.env.USER_KEYPAIR_OVERRIDE || process.env.MB_PAYER_KEYPAIR; + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type (async function main() { + /// + /// Wallet+Client setup + /// + const options = AnchorProvider.defaultOptions(); + const connection = new Connection(CLUSTER_URL!, options); + const user = Keypair.fromSecretKey(Buffer.from(JSON.parse(USER_KEYPAIR!))); + const userWallet = new Wallet(user); + const userProvider = new AnchorProvider(connection, userWallet, options); + const client = await MangoClient.connect( + userProvider, + CLUSTER, + MANGO_V4_ID[CLUSTER], + { + idsSource: 'get-program-accounts', + }, + ); + const group = await client.getGroup(new PublicKey('MANGO_V4_MAIN_GROUP')); + await group.reloadAll(client); - // get all oracles to crank - // maybe support more than one mango group - // maybe support additional via csv env param - + /// + /// Prepare all oracles we want to crank + /// - // loop indefinitely + // oracles for tokens + const oracles1 = Array.from(group.banksMapByName.values()) + .filter( + (b) => + !( + b[0].nativeDeposits().eq(ZERO_I80F48()) && + b[0].nativeBorrows().eq(ZERO_I80F48()) && + b[0].reduceOnly == 1 + ), + ) + .map((b) => { + return { + oraclePk: b[0].oracle, + oracleConfig: b[0].oracleConfig, + name: b[0].name, + }; + }); - // filter candidates for this iteration + // oracles for perp markets + const oracles2 = Array.from(group.perpMarketsMapByName.values()).map((b) => { + return { + oraclePk: b[0].oracle, + oracleConfig: b[0].oracleConfig, + name: b[0].name, + }; + }); - // build pullix for each + // fallback oracles for tokens + const oracles3 = Array.from(group.banksMapByName.values()) + .filter( + (b) => + !( + b[0].nativeDeposits().eq(ZERO_I80F48()) && + b[0].nativeBorrows().eq(ZERO_I80F48()) && + b[0].reduceOnly == 1 + ), + ) + .map((b) => { + return { + oraclePk: b[0].oracle, + oracleConfig: b[0].oracleConfig, + name: b[0].name, + }; + }) + .filter((item) => !item.oraclePk.equals(PublicKey.default)); + const oracles = oracles1.concat(oracles2).concat(oracles3); - // batch them + /// Manually exclude some + // TODO + /// Maybe support more than one mango group + // TODO + /// Maybe support additional via csv env param + // TODO + + /// + /// Filter for sb on demand oracles + /// + // TODO ensure ai is not null + const ais = await client.program.provider.connection.getMultipleAccountsInfo( + oracles.map((item) => item.oraclePk), + ); + const filteredOracles = oracles + .map((o, i) => { + return { oracle: o, ai: ais[i] }; + }) + .filter((item) => item.ai?.owner.equals(SB_ON_DEMAND_PID)); + + /// + /// sb + /// + const idl = await Program.fetchIdl(SB_ON_DEMAND_PID, client.program.provider); + const sbOnDemandProgram = new Program(idl!, client.program.provider); + const queue = new PublicKey('A43DyUGA7s8eXPxqEjJY6EBu1KKbNgfxF8h17VAHn13w'); + + /// + /// Loop indefinitely + /// + // eslint-disable-next-line no-constant-condition + while (true) { + const slot = await client.connection.getSlot(); + + // filter candidates for this iteration + + // 1. stale + const staleOracles = new Array<{ + oracle: { + oraclePk: PublicKey; + oracleConfig: OracleConfig; + }; + ai: AccountInfo | null; + }>(); + for (const item of filteredOracles) { + const res = await parseSwitchboardOracle( + item.oracle.oraclePk, + item.ai!, + client.connection, + ); + + if (slot > res.lastUpdatedSlot) { + if ( + slot - res.lastUpdatedSlot > + item.oracle.oracleConfig.maxStalenessSlots.toNumber() + ) { + staleOracles.push(item); + } + } + } + + // 2. variance + // TODO + const varianceThresholdCrossedOracles = []; + + // 3. stale or variance + // TODO verify this works + const oraclesToCrank = intersection( + staleOracles, + varianceThresholdCrossedOracles, + ); + + /// Build pull ixs + const pullIxs: TransactionInstruction[] = []; + const lutOwners: (PublicKey | Oracle)[] = []; + for (const oracle of oraclesToCrank) { + const pullFeed = new PullFeed( + sbOnDemandProgram as any, + new PublicKey(oracle.oracle.oraclePk), + ); + + const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( + 'pullFeedAccountData', + oraclesToCrank.ai.data, + ); + + const conf = { + queue: queue, + maxVariance: decodedPullFeed.maxVariance.toNumber(), + minResponses: decodedPullFeed.minResponses, + numSignatures: 3, // TODO hardcoded + minSampleSize: decodedPullFeed.minSampleSize, + maxStaleness: decodedPullFeed.maxStaleness, + }; + const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); + + const lutOwners_ = [...responses.map((x) => x.oracle), pullFeed.pubkey]; + lutOwners.push(...lutOwners_); + pullIxs.push(pullIx!); + } + + for (const c of chunk(pullIxs, 5)) { + const tx = await asV0Tx({ + connection, + ixs: [...c], + signers: [user], + computeUnitPrice: 200_000, + computeUnitLimitMultiple: 1.3, + lookupTables: await loadLookupTables(lutOwners), + }); + + const txOpts = { + commitment: 'processed' as Commitment, + skipPreflight: true, + maxRetries: 0, + }; + + const sim = await client.connection.simulateTransaction(tx, txOpts); + const sig = await client.connection.sendTransaction(tx, txOpts); + console.log(`updated in ${sig}`); // TODO add token names + } + + await new Promise((r) => setTimeout(r, 5000)); + } }); From b2671ba7fb95e1b8ba01de18fcb3fef8a053f664 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Tue, 25 Jun 2024 15:14:42 +0200 Subject: [PATCH 04/40] update Signed-off-by: microwavedcola1 --- ts/client/src/accounts/oracle.ts | 1 - ts/client/src/utils.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index dded3d208..4efd3dd52 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -162,7 +162,6 @@ export async function parseSwitchboardOracle( options, ); const idl = await Program.fetchIdl(SB_ON_DEMAND_PID, provider); - // console.log(idl); sbOnDemandProgram = new Program(idl!, provider); } return parseSwitchboardOnDemandOracle( diff --git a/ts/client/src/utils.ts b/ts/client/src/utils.ts index 6493a38d3..a802c39a6 100644 --- a/ts/client/src/utils.ts +++ b/ts/client/src/utils.ts @@ -125,7 +125,7 @@ export async function buildFetch(): Promise< > { let fetch = globalThis?.fetch; if (!fetch && process?.versions?.node) { - fetch = (await import('node-fetch')).default; + fetch = (await import('node-fetch')).default as any; } return fetch; } From a5ba37be7d62b94e0f9c7fc0ce60261da7a6d739 Mon Sep 17 00:00:00 2001 From: Serge Farny Date: Tue, 25 Jun 2024 17:02:33 +0200 Subject: [PATCH 05/40] Program: add switchboard on demand oracle support (#974) --------- Co-authored-by: Mitch Gildenberg (cherry picked from commit ed28450b9874c674bee5b9d3d8f8f0058130261b) --- Cargo.lock | 768 +++++++++++------- programs/mango-v4/Cargo.toml | 1 + ...SDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf.bin | Bin 0 -> 3208 bytes programs/mango-v4/src/state/oracle.rs | 103 ++- 4 files changed, 593 insertions(+), 279 deletions(-) create mode 100644 programs/mango-v4/resources/test/EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf.bin diff --git a/Cargo.lock b/Cargo.lock index a54abdb97..2e8774087 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,8 +121,8 @@ checksum = "faa5be5b72abea167f87c868379ba3c2be356bfca9e6f474fd055fa0f7eeb4f2" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "regex", "syn 1.0.109", ] @@ -136,8 +136,8 @@ dependencies = [ "anchor-syn", "anyhow", "bs58 0.5.0", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "rustversion", "syn 1.0.109", ] @@ -149,7 +149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59948e7f9ef8144c2aefb3f32a40c5fce2798baeec765ba038389e82301017ef" dependencies = [ "anchor-syn", - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", "syn 1.0.109", ] @@ -160,8 +160,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc753c9d1c7981cb8948cf7e162fb0f64558999c0413058e2d43df1df5448086" dependencies = [ "anchor-syn", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -173,8 +173,8 @@ checksum = "f38b4e172ba1b52078f53fdc9f11e3dc0668ad27997838a0aad2d148afac8c97" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -186,8 +186,8 @@ checksum = "4eebd21543606ab61e2d83d9da37d24d3886a49f390f9c43a1964735e8c0f0d5" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -218,8 +218,8 @@ checksum = "ec4720d899b3686396cced9508f23dab420f1308344456ec78ef76f98fda42af" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -229,8 +229,8 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f495e85480bd96ddeb77b71d499247c7d4e8b501e75ecb234e9ef7ae7bd6552a" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -280,11 +280,11 @@ dependencies = [ "anyhow", "bs58 0.5.0", "heck 0.3.3", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "syn 1.0.109", "thiserror", ] @@ -366,7 +366,7 @@ dependencies = [ "derivative", "digest 0.10.7", "itertools", - "num-bigint 0.4.4", + "num-bigint 0.4.5", "num-traits", "paste", "rustc_version 0.4.0", @@ -379,7 +379,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote 1.0.33", + "quote 1.0.36", "syn 1.0.109", ] @@ -389,10 +389,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ - "num-bigint 0.4.4", + "num-bigint 0.4.5", "num-traits", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -418,7 +418,7 @@ dependencies = [ "ark-serialize-derive", "ark-std", "digest 0.10.7", - "num-bigint 0.4.4", + "num-bigint 0.4.5", ] [[package]] @@ -427,8 +427,8 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -500,8 +500,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", "synstructure", ] @@ -512,8 +512,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -590,8 +590,8 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -601,20 +601,20 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -750,9 +750,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -800,12 +800,12 @@ dependencies = [ "lazycell", "peeking_take_while", "prettyplease 0.2.15", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "regex", "rustc-hash", "shlex", - "syn 2.0.37", + "syn 2.0.68", ] [[package]] @@ -918,7 +918,7 @@ dependencies = [ "borsh-derive-internal 0.9.3", "borsh-schema-derive-internal 0.9.3", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", "syn 1.0.109", ] @@ -931,7 +931,7 @@ dependencies = [ "borsh-derive-internal 0.10.3", "borsh-schema-derive-internal 0.10.3", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", "syn 1.0.109", ] @@ -941,8 +941,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -952,8 +952,8 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -963,8 +963,8 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -974,8 +974,8 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -1068,9 +1068,9 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -1162,8 +1162,8 @@ name = "checked_math" version = "0.1.0" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", "trybuild", ] @@ -1252,8 +1252,8 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -1536,8 +1536,8 @@ checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "strsim 0.10.0", "syn 1.0.109", ] @@ -1550,10 +1550,10 @@ checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "strsim 0.10.0", - "syn 2.0.37", + "syn 2.0.68", ] [[package]] @@ -1563,7 +1563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ "darling_core 0.14.4", - "quote 1.0.33", + "quote 1.0.36", "syn 1.0.109", ] @@ -1574,8 +1574,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", - "quote 1.0.33", - "syn 2.0.37", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -1624,7 +1624,7 @@ dependencies = [ "asn1-rs", "displaydoc", "nom 7.1.3", - "num-bigint 0.4.4", + "num-bigint 0.4.5", "num-traits", "rusticata-macros", ] @@ -1647,8 +1647,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -1668,8 +1668,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ "darling 0.14.4", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -1690,8 +1690,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "rustc_version 0.4.0", "syn 1.0.109", ] @@ -1793,9 +1793,9 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -1871,7 +1871,7 @@ dependencies = [ "derivation-path", "ed25519-dalek", "hmac 0.12.1", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -1881,8 +1881,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0042ff8246a363dbe77d2ceedb073339e85a804b9a47636c6e016a9a32c05f" dependencies = [ "enum-ordinalize", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -1922,9 +1922,9 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -1933,11 +1933,11 @@ version = "3.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4f76552f53cefc9a7f64987c3701b99d982f7690606fd67de1d09712fbf52f1" dependencies = [ - "num-bigint 0.4.4", + "num-bigint 0.4.5", "num-traits", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -1955,8 +1955,8 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -1988,6 +1988,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased-serde" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4adbf0983fe06bd3a5c19c8477a637c2389feb0994eca7a59e3b961054aa7c0a" +dependencies = [ + "serde", +] + [[package]] name = "errno" version = "0.3.3" @@ -2247,9 +2256,9 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -2461,7 +2470,7 @@ version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "byteorder", "crossbeam-channel", "flate2 1.0.27", @@ -2475,7 +2484,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bytes 1.5.0", "headers-core", "http", @@ -2970,8 +2979,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" dependencies = [ "proc-macro-crate 0.1.5", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -3206,15 +3215,34 @@ dependencies = [ "base64 0.12.3", "digest 0.9.0", "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", + "libsecp256k1-core 0.2.2", + "libsecp256k1-gen-ecmult 0.2.1", + "libsecp256k1-gen-genmult 0.2.1", "rand 0.7.3", "serde", "sha2 0.9.9", "typenum", ] +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core 0.3.0", + "libsecp256k1-gen-ecmult 0.3.0", + "libsecp256k1-gen-genmult 0.3.0", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum", +] + [[package]] name = "libsecp256k1-core" version = "0.2.2" @@ -3226,13 +3254,33 @@ dependencies = [ "subtle", ] +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + [[package]] name = "libsecp256k1-gen-ecmult" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" dependencies = [ - "libsecp256k1-core", + "libsecp256k1-core 0.2.2", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core 0.3.0", ] [[package]] @@ -3241,7 +3289,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" dependencies = [ - "libsecp256k1-core", + "libsecp256k1-core 0.2.2", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core 0.3.0", ] [[package]] @@ -3294,6 +3351,9 @@ name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +dependencies = [ + "value-bag", +] [[package]] name = "lru" @@ -3359,7 +3419,7 @@ dependencies = [ "anyhow", "async-channel", "async-trait", - "base64 0.21.4", + "base64 0.21.7", "bs58 0.5.0", "bytemuck", "bytes 1.5.0", @@ -3400,7 +3460,7 @@ dependencies = [ "itertools", "lazy_static", "log 0.4.20", - "num 0.4.1", + "num 0.4.3", "num_enum 0.5.11", "openbook-v2", "pyth-sdk-solana", @@ -3418,6 +3478,7 @@ dependencies = [ "spl-associated-token-account 1.1.3", "spl-token 3.5.0", "static_assertions", + "switchboard-on-demand", "switchboard-program", "switchboard-solana", ] @@ -3431,7 +3492,7 @@ dependencies = [ "anchor-spl", "anyhow", "async-channel", - "base64 0.21.4", + "base64 0.21.7", "clap 3.2.25", "dotenv", "fixed 1.11.0 (git+https://github.com/blockworks-foundation/fixed.git?branch=v1.11.0-borsh0_10-mango)", @@ -3826,8 +3887,8 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -3876,7 +3937,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12989bc45715b0ee91944855130131479f9c772e198a910c3eb0ea327d5bffc3" dependencies = [ - "quote 1.0.33", + "quote 1.0.36", "syn 1.0.109", ] @@ -3886,7 +3947,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a739019e11d93661a64ef5fe108ab17c79b35961e944442ff6efdd460ad01a" dependencies = [ - "quote 1.0.33", + "quote 1.0.36", "syn 1.0.109", ] @@ -4023,15 +4084,15 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint 0.4.4", - "num-complex 0.4.4", + "num-bigint 0.4.5", + "num-complex 0.4.6", "num-integer", "num-iter", - "num-rational 0.4.1", + "num-rational 0.4.2", "num-traits", ] @@ -4048,11 +4109,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -4069,9 +4129,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -4082,8 +4142,8 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -4093,26 +4153,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg 1.1.0", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg 1.1.0", "num-integer", @@ -4133,21 +4192,20 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg 1.1.0", - "num-bigint 0.4.4", + "num-bigint 0.4.5", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg 1.1.0", ] @@ -4196,8 +4254,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -4208,9 +4266,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -4220,9 +4278,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -4300,9 +4358,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -4376,8 +4434,8 @@ checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -4564,9 +4622,9 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -4629,9 +4687,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83145eba741b050ef981a9a1838c843fa7665e154383325aa8b440ae703180a2" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -4653,7 +4711,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "byteorder", "bytes 1.5.0", "fallible-iterator", @@ -4661,7 +4719,7 @@ dependencies = [ "md-5", "memchr", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "stringprep", ] @@ -4700,8 +4758,8 @@ version = "0.3.3" source = "git+https://github.com/nolanderc/rust-postgres-query?rev=b4422051c8a31fbba4a35f88004c1cefb1878dd5#b4422051c8a31fbba4a35f88004c1cefb1878dd5" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -4717,7 +4775,7 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", "syn 1.0.109", ] @@ -4727,8 +4785,8 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ - "proc-macro2 1.0.67", - "syn 2.0.37", + "proc-macro2 1.0.86", + "syn 2.0.68", ] [[package]] @@ -4767,8 +4825,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", "version_check 0.9.4", ] @@ -4779,8 +4837,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "version_check 0.9.4", ] @@ -4801,9 +4859,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4893,8 +4951,8 @@ checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -4906,8 +4964,8 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -5055,11 +5113,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", ] [[package]] @@ -5404,7 +5462,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" dependencies = [ "async-compression", - "base64 0.21.4", + "base64 0.21.7", "bytes 1.5.0", "encoding_rs", "futures-core", @@ -5526,7 +5584,7 @@ version = "1.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4903d8db81d2321699ca8318035d6ff805c548868df435813968795a802171b2" dependencies = [ - "quote 1.0.33", + "quote 1.0.36", "rust_decimal", ] @@ -5624,7 +5682,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", ] [[package]] @@ -5697,8 +5755,8 @@ version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "serde_derive_internals", "syn 1.0.109", ] @@ -5730,9 +5788,9 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -5813,9 +5871,9 @@ version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -5824,11 +5882,20 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] +[[package]] +name = "serde_fmt" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" +dependencies = [ + "serde", +] + [[package]] name = "serde_json" version = "1.0.107" @@ -5869,9 +5936,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" dependencies = [ "darling 0.20.3", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -5980,7 +6047,7 @@ dependencies = [ "anyhow", "async-channel", "async-trait", - "base64 0.21.4", + "base64 0.21.7", "bs58 0.3.1", "bytemuck", "chrono", @@ -6025,7 +6092,7 @@ dependencies = [ "anyhow", "async-channel", "async-trait", - "base64 0.21.4", + "base64 0.21.7", "bs58 0.3.1", "bytemuck", "chrono", @@ -6126,7 +6193,7 @@ name = "services-mango-lib" version = "0.1.0" dependencies = [ "anyhow", - "base64 0.21.4", + "base64 0.21.7", "native-tls", "postgres-native-tls", "postgres-types", @@ -6210,9 +6277,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -6256,8 +6323,8 @@ version = "0.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63927d22a1e8b74bda98cc6e151fcdf178b7abb0dc6c4f81e0bbf5ffe2fc4ec8" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "shank_macro_impl", "syn 1.0.109", ] @@ -6269,8 +6336,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce03403df682f80f4dc1efafa87a4d0cb89b03726d0565e6364bdca5b9a441" dependencies = [ "anyhow", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "serde", "syn 1.0.109", ] @@ -6414,7 +6481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0ada16ccd5ca6884ae28b716211c4f09d22225a9ebde14eccd4f605cc321e42" dependencies = [ "Inflector", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bs58 0.4.0", "bv", @@ -6526,7 +6593,7 @@ checksum = "70b84a554f12f89c72f3c2dea973a5105740814aeebfb04998cc0afd9e2e6a2e" dependencies = [ "bincode", "byteorder", - "libsecp256k1", + "libsecp256k1 0.6.0", "log 0.4.20", "rand 0.7.3", "solana-measure", @@ -6740,7 +6807,7 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "solana-frozen-abi-macro", "subtle", "thiserror", @@ -6752,10 +6819,10 @@ version = "1.16.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dabde7fbd88a68eb083ae9d6d5f6855b7ba1bfc45d200c786b1b448ac49da5f" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "rustc_version 0.4.0", - "syn 2.0.37", + "syn 2.0.68", ] [[package]] @@ -6839,7 +6906,7 @@ dependencies = [ "scopeguard", "serde", "serde_bytes", - "sha2 0.10.7", + "sha2 0.10.8", "solana-account-decoder", "solana-bpf-loader-program", "solana-entry", @@ -7005,7 +7072,7 @@ dependencies = [ "ark-ff", "ark-serialize", "array-bytes", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bitflags 1.3.2", "blake3", @@ -7023,10 +7090,10 @@ dependencies = [ "js-sys", "lazy_static", "libc", - "libsecp256k1", + "libsecp256k1 0.6.0", "log 0.4.20", "memoffset 0.9.0", - "num-bigint 0.4.4", + "num-bigint 0.4.5", "num-derive 0.3.3", "num-traits", "parking_lot 0.12.1", @@ -7038,7 +7105,7 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "sha3 0.10.8", "solana-frozen-abi", "solana-frozen-abi-macro", @@ -7055,7 +7122,7 @@ version = "1.16.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f65907a405764cda63be89335ffd2138ade18f065e5cae09d20adab7fb09502" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bincode", "eager", "enum-iterator", @@ -7085,7 +7152,7 @@ checksum = "48eaefd61e16f94f3fb7c4ad9a3cbb18666d28f631ea1420d985203ea8b87861" dependencies = [ "assert_matches", "async-trait", - "base64 0.21.4", + "base64 0.21.7", "bincode", "chrono-humanize", "crossbeam-channel", @@ -7192,7 +7259,7 @@ version = "1.16.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afe5477133fd83e423a9ac2339a1c3e209920c328cd024b3066431362d7c43f" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bincode", "bs58 0.4.0", "crossbeam-channel", @@ -7248,7 +7315,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2771ac12cdbde1aa6b55a129947f1428bb44d14314059c1e69674e1d58aaf9e1" dependencies = [ "async-trait", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bs58 0.4.0", "indicatif", @@ -7273,7 +7340,7 @@ version = "1.16.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f401e2ae586fd60c1c8c0f406be521bfe4889c6c2854fbb76bd20e8bc2d57284" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bs58 0.4.0", "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest", @@ -7378,7 +7445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57f4046d0d487e3d79be809ff29c63c1484793956e6ccbc5d3307b0aafbf989d" dependencies = [ "assert_matches", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bitflags 1.3.2", "borsh 0.10.3", @@ -7395,7 +7462,7 @@ dependencies = [ "itertools", "js-sys", "lazy_static", - "libsecp256k1", + "libsecp256k1 0.6.0", "log 0.4.20", "memmap2", "num-derive 0.3.3", @@ -7412,7 +7479,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_with", - "sha2 0.10.7", + "sha2 0.10.8", "sha3 0.10.8", "solana-frozen-abi", "solana-frozen-abi-macro", @@ -7431,10 +7498,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "760fdfd4b7edb02fd9173a6dcec899ffae06ac21b66b65f8c7c5f3d17b12fa64" dependencies = [ "bs58 0.4.0", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "rustversion", - "syn 2.0.37", + "syn 2.0.68", ] [[package]] @@ -7619,7 +7686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bdf7379a72c051d7879f1c36cfdab5fed0653a2a613718bc5d343e44e603401" dependencies = [ "Inflector", - "base64 0.21.4", + "base64 0.21.7", "bincode", "borsh 0.9.3", "bs58 0.4.0", @@ -7713,7 +7780,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bdec366a15133a70a8dfc4f027b5d0f508bd7cb46af11971076c9ebaf9ede2d" dependencies = [ "aes-gcm-siv", - "base64 0.21.4", + "base64 0.21.7", "bincode", "bytemuck", "byteorder", @@ -7825,9 +7892,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4fa8f409b5c5e0ac571df17c981ae1424b204743daa4428430627d38717caf5" dependencies = [ - "quote 1.0.33", + "quote 1.0.36", "spl-discriminator-syn", - "syn 2.0.37", + "syn 2.0.68", ] [[package]] @@ -7836,10 +7903,10 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21968d7da2f0a624c509f24580c3fee70b364a6886d90709e679e64f572eca2f" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "solana-program", - "syn 2.0.37", + "syn 2.0.68", "thiserror", ] @@ -7893,10 +7960,10 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6709c5f41fefb730f2bd8464da741079cf0efd1d0f522e041224b98d431b9b3" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "solana-program", - "syn 2.0.37", + "syn 2.0.68", ] [[package]] @@ -8082,8 +8149,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "rustversion", "syn 1.0.109", ] @@ -8100,6 +8167,84 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" +[[package]] +name = "sval" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53eb957fbc79a55306d5d25d87daf3627bc3800681491cda0709eef36c748bfe" + +[[package]] +name = "sval_buffer" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e860aef60e9cbf37888d4953a13445abf523c534640d1f6174d310917c410d" +dependencies = [ + "sval", + "sval_ref", +] + +[[package]] +name = "sval_dynamic" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3f2b07929a1127d204ed7cb3905049381708245727680e9139dac317ed556f" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_fmt" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e188677497de274a1367c4bda15bd2296de4070d91729aac8f0a09c1abf64d" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_json" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f456c07dae652744781f2245d5e3b78e6a9ebad70790ac11eb15dbdbce5282" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_nested" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "886feb24709f0476baaebbf9ac10671a50163caa7e439d7a7beb7f6d81d0a6fb" +dependencies = [ + "sval", + "sval_buffer", + "sval_ref", +] + +[[package]] +name = "sval_ref" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be2e7fc517d778f44f8cb64140afa36010999565528d48985f55e64d45f369ce" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_serde" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79bf66549a997ff35cd2114a27ac4b0c2843280f2cfa84b240d169ecaa0add46" +dependencies = [ + "serde", + "sval", + "sval_nested", +] + [[package]] name = "switchboard-common" version = "0.9.0" @@ -8112,7 +8257,50 @@ dependencies = [ "serde", "serde_json", "sgx-quote", - "sha2 0.10.7", + "sha2 0.10.8", +] + +[[package]] +name = "switchboard-common" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96fe58be35530580b729fa5d846661c89a007982527f4ff0ca6010168564159" +dependencies = [ + "base64 0.21.7", + "hex", + "log 0.4.20", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3 0.10.8", +] + +[[package]] +name = "switchboard-on-demand" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4abd6842db96de13759d86a317a9083aa0baa3a0da4f051c29b21efc41f6c0" +dependencies = [ + "arc-swap", + "async-trait", + "base64 0.21.7", + "bincode", + "borsh 0.10.3", + "bytemuck", + "futures 0.3.28", + "lazy_static", + "libsecp256k1 0.7.1", + "log 0.4.20", + "num 0.4.3", + "rust_decimal", + "serde", + "serde_json", + "sha2 0.10.8", + "solana-address-lookup-table-program", + "solana-program", + "spl-associated-token-account 2.1.0", + "spl-token 3.5.0", + "switchboard-common 0.11.3", ] [[package]] @@ -8163,7 +8351,7 @@ dependencies = [ "solana-client", "solana-program", "superslice", - "switchboard-common", + "switchboard-common 0.9.0", "tokio", "url 2.4.1", ] @@ -8222,19 +8410,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.37" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "unicode-ident", ] @@ -8250,8 +8438,8 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", "unicode-xid 0.2.4", ] @@ -8297,8 +8485,8 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee42b4e559f17bce0385ebf511a7beb67d5cc33c12c96b7f4e9789919d9c10f" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -8354,9 +8542,9 @@ version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -8510,8 +8698,8 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -8804,7 +8992,7 @@ dependencies = [ "async-stream 0.3.5", "async-trait", "axum", - "base64 0.21.4", + "base64 0.21.7", "bytes 1.5.0", "flate2 1.0.27", "futures-core", @@ -8834,9 +9022,9 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757" dependencies = [ - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", "prost-build 0.9.0", - "quote 1.0.33", + "quote 1.0.36", "syn 1.0.109", ] @@ -8847,9 +9035,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" dependencies = [ "prettyplease 0.1.25", - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", "prost-build 0.11.9", - "quote 1.0.33", + "quote 1.0.36", "syn 1.0.109", ] @@ -8860,9 +9048,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6fdaae4c2c638bb70fe42803a26fbd6fc6ac8c72f5c59f67ecc2a2dcabf4b07" dependencies = [ "prettyplease 0.1.25", - "proc-macro2 1.0.67", + "proc-macro2 1.0.86", "prost-build 0.11.9", - "quote 1.0.33", + "quote 1.0.36", "syn 1.0.109", ] @@ -8930,9 +9118,9 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] @@ -9261,6 +9449,42 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +dependencies = [ + "value-bag-serde1", + "value-bag-sval2", +] + +[[package]] +name = "value-bag-serde1" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccacf50c5cb077a9abb723c5bcb5e0754c1a433f1e1de89edc328e2760b6328b" +dependencies = [ + "erased-serde", + "serde", + "serde_fmt", +] + +[[package]] +name = "value-bag-sval2" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1785bae486022dfb9703915d42287dcb284c1ee37bd1080eeba78cc04721285b" +dependencies = [ + "sval", + "sval_buffer", + "sval_dynamic", + "sval_fmt", + "sval_json", + "sval_ref", + "sval_serde", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -9378,9 +9602,9 @@ dependencies = [ "bumpalo", "log 0.4.20", "once_cell", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -9402,7 +9626,7 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ - "quote 1.0.33", + "quote 1.0.36", "wasm-bindgen-macro-support", ] @@ -9412,9 +9636,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9841,9 +10065,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.68", ] [[package]] diff --git a/programs/mango-v4/Cargo.toml b/programs/mango-v4/Cargo.toml index 101d3bdbb..c54c1555e 100644 --- a/programs/mango-v4/Cargo.toml +++ b/programs/mango-v4/Cargo.toml @@ -50,6 +50,7 @@ static_assertions = "1.1" # note: switchboard-common 0.8.19 is broken - use 0.8.18 instead switchboard-program = "0.2" switchboard-v2 = { package = "switchboard-solana", version = "0.28" } +switchboard-on-demand = { version = "0.1.11" } openbook-v2 = { git = "https://github.com/openbook-dex/openbook-v2.git", features = [ diff --git a/programs/mango-v4/resources/test/EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf.bin b/programs/mango-v4/resources/test/EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf.bin new file mode 100644 index 0000000000000000000000000000000000000000..cf9cc1d32b2036c0702fe4c2ae93931b5b00bd74 GIT binary patch literal 3208 zcmX>iopXfi`fZI%45!yl*({&7PwU^V#21b-S8`V_jtMYRpHt-bz}IV?{Ttm_AqFJy zGJcwL_)FzgUwI&cd*{tDn78=vs>A)=pYHB452&1$(K&UmrNE-I9M{X(r(GbVe{I5a z=1&Wwez*TVd|~0j{8uUy4js?=r;)DYmQ|iTw?mSUek7-jGDkyTGz3ONU^E0qLtr!n zhzx;^MeN&R%{TMrO)Oz)zEzqqL3Div2M25G0p=r%4f*zI+&r7bA}O15HFBwXUgq*S z$9{%}-h1_A#^FUjHor?}YQOksm!_6k{x{*i72C3fp3Eyzu@GD9ch}gWWzE~Od^~z{ zvo} Result( oracle_type: OracleType::SwitchboardV1, } } + OracleType::SwitchboardOnDemand => { + fn from_foreign_error(e: impl std::fmt::Display) -> Error { + error_msg!("{}", e) + } + let feed = bytemuck::from_bytes::(&data[8..]); + let ui_price: f64 = feed + .value() + .ok_or_else(|| error_msg!("missing price"))? + .try_into() + .map_err(from_foreign_error)?; + let ui_deviation: f64 = feed + .std_dev() + .ok_or_else(|| error_msg!("missing deviation"))? + .try_into() + .map_err(from_foreign_error)?; + let last_update_slot = feed.result.min_slot; + + let decimals = QUOTE_DECIMALS - (base_decimals as i8); + let decimal_adj = power_of_ten(decimals); + let price = I80F48::from_num(ui_price) * decimal_adj; + let deviation = I80F48::from_num(ui_deviation) * decimal_adj; + require_gte!(price, 0); + OracleState { + price, + last_update_slot: last_update_slot, + deviation, + oracle_type: OracleType::SwitchboardOnDemand, + } + } OracleType::OrcaCLMM => { let whirlpool = load_orca_pool_state(oracle_info)?; let clmm_price = whirlpool.get_clmm_price(); @@ -484,6 +525,11 @@ mod tests { OracleType::OrcaCLMM, orca_mainnet_whirlpool::ID, ), + ( + "EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf", + OracleType::SwitchboardOnDemand, + switchboard_on_demand_mainnet_oracle::ID, + ), ]; for fixture in fixtures { @@ -524,6 +570,49 @@ mod tests { } } + #[test] + pub fn test_switchboard_on_demand_price() -> Result<()> { + // add ability to find fixtures + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("resources/test"); + + let fixtures = vec![( + "EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf", + OracleType::SwitchboardOnDemand, + switchboard_on_demand_mainnet_oracle::ID, + 6, + )]; + + for fixture in fixtures { + let file = format!("resources/test/{}.bin", fixture.0); + let mut data = read_file(find_file(&file).unwrap()); + let data = RefCell::new(&mut data[..]); + let ai = &AccountInfoRef { + key: &Pubkey::from_str(fixture.0).unwrap(), + owner: &fixture.2, + data: data.borrow(), + }; + let base_decimals = fixture.3; + + let sw_ais = OracleAccountInfos { + oracle: ai, + fallback_opt: None, + usdc_opt: None, + sol_opt: None, + }; + let sw = oracle_state_unchecked(&sw_ais, base_decimals).unwrap(); + + match fixture.1 { + OracleType::SwitchboardOnDemand => { + assert_eq!(sw.price, I80F48::from_num(61200.109991665549598697)) + } + _ => unimplemented!(), + } + } + + Ok(()) + } + #[test] pub fn test_clmm_prices() -> Result<()> { // add ability to find fixtures From 28a636857eda69370de3da5525d3e62c772a0b8e Mon Sep 17 00:00:00 2001 From: Serge Farny Date: Wed, 26 Jun 2024 08:51:41 +0200 Subject: [PATCH 06/40] token update index and rate- skip bad oracle (#975) Program: skip index and rate update when oracle is invalid (cherry picked from commit d0cb8b9b0c60ca4c2395452d6c2e16e589ffa171) --- bin/keeper/src/crank.rs | 21 ++----------- .../token_update_index_and_rate.rs | 31 ++++++++++++++----- programs/mango-v4/src/lib.rs | 10 +++++- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/bin/keeper/src/crank.rs b/bin/keeper/src/crank.rs index 5884c6ef5..3d09e5868 100644 --- a/bin/keeper/src/crank.rs +++ b/bin/keeper/src/crank.rs @@ -105,7 +105,6 @@ pub async fn runner( .context .tokens .keys() - // TODO: grouping tokens whose oracle might have less confidencen e.g. ORCA with the rest, fails whole ix // TokenUpdateIndexAndRate is known to take max 71k cu // from cargo test-bpf local tests // chunk size of 8 seems to be max before encountering "VersionedTransaction too large" issues @@ -211,7 +210,7 @@ pub async fn loop_update_index_and_rate( None, ), data: anchor_lang::InstructionData::data( - &mango_v4::instruction::TokenUpdateIndexAndRate {}, + &mango_v4::instruction::TokenUpdateIndexAndRateResilient {}, ), }; let mut banks = banks_for_a_token @@ -224,20 +223,6 @@ pub async fn loop_update_index_and_rate( .collect::>(); ix.accounts.append(&mut banks); - - let sim_result = match client.simulate(vec![ix.clone()]).await { - Ok(response) => response.value, - Err(e) => { - error!(token.name, "simulation request error: {e:?}"); - continue; - } - }; - - if let Some(e) = sim_result.err { - error!(token.name, "simulation error: {e:?} {:?}", sim_result.logs); - continue; - } - instructions.push(ix); } let pre = Instant::now(); @@ -466,7 +451,7 @@ pub async fn loop_charge_collateral_fees( collateral_fee_interval, max_cu_when_batching, ) - .await + .await { Ok(()) => {} Err(err) => { @@ -531,7 +516,7 @@ async fn charge_collateral_fees_inner( &ix_to_send, max_cu_when_batching, ) - .await; + .await; info!("charge collateral fees: {:?}", txsigs); Ok(()) diff --git a/programs/mango-v4/src/instructions/token_update_index_and_rate.rs b/programs/mango-v4/src/instructions/token_update_index_and_rate.rs index a2c7d14c3..6df830b34 100644 --- a/programs/mango-v4/src/instructions/token_update_index_and_rate.rs +++ b/programs/mango-v4/src/instructions/token_update_index_and_rate.rs @@ -18,7 +18,10 @@ pub mod compute_budget { declare_id!("ComputeBudget111111111111111111111111111111"); } -pub fn token_update_index_and_rate(ctx: Context) -> Result<()> { +pub fn token_update_index_and_rate( + ctx: Context, + early_exit_on_invalid_oracle: bool, +) -> Result<()> { { let ixs = ctx.accounts.instructions.as_ref(); @@ -71,6 +74,26 @@ pub fn token_update_index_and_rate(ctx: Context) -> Res { let mut some_bank = ctx.remaining_accounts[0].load_mut::()?; + let oracle_ref = &AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?; + let price = some_bank.oracle_price( + &OracleAccountInfos::from_reader(oracle_ref), + Some(clock.slot), + ); + + // Early exit if oracle is invalid + // Warning: do not change any state before this check + let price = match price { + Ok(p) => p, + Err(e) => { + return if early_exit_on_invalid_oracle { + msg!("Invalid oracle state: {}", e); + Ok(()) + } else { + Err(e) + } + } + }; + // Limit the maximal time interval that interest is applied for. This means we won't use // a fixed interest rate for a very long time period in exceptional circumstances, like // when there is a solana downtime or the security council disables this instruction. @@ -89,12 +112,6 @@ pub fn token_update_index_and_rate(ctx: Context) -> Res now_ts, ); - let oracle_ref = &AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?; - let price = some_bank.oracle_price( - &OracleAccountInfos::from_reader(oracle_ref), - Some(clock.slot), - )?; - some_bank .stable_price_model .update(now_ts as u64, price.to_num()); diff --git a/programs/mango-v4/src/lib.rs b/programs/mango-v4/src/lib.rs index 533434b14..ac27e52a7 100644 --- a/programs/mango-v4/src/lib.rs +++ b/programs/mango-v4/src/lib.rs @@ -324,7 +324,15 @@ pub mod mango_v4 { pub fn token_update_index_and_rate(ctx: Context) -> Result<()> { #[cfg(feature = "enable-gpl")] - instructions::token_update_index_and_rate(ctx)?; + instructions::token_update_index_and_rate(ctx, false)?; + Ok(()) + } + + pub fn token_update_index_and_rate_resilient( + ctx: Context, + ) -> Result<()> { + #[cfg(feature = "enable-gpl")] + instructions::token_update_index_and_rate(ctx, true)?; Ok(()) } From 71ac3d2e8aabdba43ea6ed3d6c666c3fab616a93 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Thu, 27 Jun 2024 13:11:22 +0200 Subject: [PATCH 07/40] ts: sb on demand oracles part 2 Signed-off-by: microwavedcola1 --- .gitignore | 1 + mango_v4.json | 33 +++ package.json | 15 +- ts/client/scripts/sb-on-demand-crank.ts | 106 +++++++-- ts/client/src/accounts/oracle.ts | 8 +- ts/client/src/mango_v4.ts | 66 ++++++ tsconfig.json | 8 + yarn.lock | 274 ++++++++++++++++++++++-- 8 files changed, 459 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index 650adae91..88e754b41 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ programs/mango-v4/src/lib-expanded.rs dist node_modules yarn-error.log +.yarn .idea .vscode diff --git a/mango_v4.json b/mango_v4.json index cc44fefe8..02dc51cc3 100644 --- a/mango_v4.json +++ b/mango_v4.json @@ -1277,6 +1277,36 @@ ], "args": [] }, + { + "name": "tokenUpdateIndexAndRateResilient", + "accounts": [ + { + "name": "group", + "isMut": false, + "isSigner": false + }, + { + "name": "mintInfo", + "isMut": false, + "isSigner": false, + "relations": [ + "oracle", + "group" + ] + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "instructions", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, { "name": "accountCreate", "accounts": [ @@ -11133,6 +11163,9 @@ }, { "name": "RaydiumCLMM" + }, + { + "name": "SwitchboardOnDemand" } ] } diff --git a/package.json b/package.json index 760e3582d..cb99b2f02 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "secp256k1": "5.0.0", "ts-mocha": "^10.0.0", "ts-node": "^10.9.1", + "tsx": "^4.15.7", "tweetnacl": "1.0.3", "typedoc": "^0.22.5", "typescript": "^4.8.4" @@ -64,7 +65,7 @@ "dependencies": { "@blockworks-foundation/mango-v4-settings": "0.14.15", "@blockworks-foundation/mangolana": "0.0.14", - "@coral-xyz/anchor": "^0.30.1", + "@coral-xyz/anchor": "^0.28.1-beta.2", "@project-serum/serum": "0.13.65", "@pythnetwork/client": "~2.14.0", "@solana/spl-token": "0.3.7", @@ -78,13 +79,9 @@ "dotenv": "^16.0.3", "fast-copy": "^3.0.1", "lodash": "^4.17.21", - "node-kraken-api": "^2.2.2" + "node-kraken-api": "^2.2.2", + "switchboard-anchor": "npm:@coral-xyz/anchor@0.30.0" }, - "resolutions": { - "@coral-xyz/anchor": "^0.28.1-beta.2", - "**/@solana/web3.js/node-fetch": "npm:@blockworks-foundation/node-fetch@2.6.11", - "**/cross-fetch/node-fetch": "npm:@blockworks-foundation/node-fetch@2.6.11", - "**/@blockworks-foundation/mangolana/node-fetch": "npm:@blockworks-foundation/node-fetch@2.6.11" - }, - "license": "MIT" + "license": "MIT", + "packageManager": "yarn@4.3.1" } diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 4855aa4d7..387bf292f 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -1,4 +1,4 @@ -import { AnchorProvider, Program, Wallet } from '@coral-xyz/anchor'; +import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor'; import { AccountInfo, Cluster, @@ -10,18 +10,22 @@ import { } from '@solana/web3.js'; import { asV0Tx, + CrossbarClient, loadLookupTables, Oracle, PullFeed, SB_ON_DEMAND_PID, } from '@switchboard-xyz/on-demand'; +import fs from 'fs'; import chunk from 'lodash/chunk'; -import intersection from 'lodash/intersection'; +import uniq from 'lodash/uniq'; +import { Program as Anchor30Program } from 'switchboard-anchor'; + import { OracleConfig } from '../src/accounts/bank'; import { parseSwitchboardOracle } from '../src/accounts/oracle'; import { MangoClient } from '../src/client'; -import { MANGO_V4_ID } from '../src/constants'; -import { ZERO_I80F48 } from '../src/numbers/I80F48'; +import { MANGO_V4_ID, MANGO_V4_MAIN_GROUP } from '../src/constants'; +import { I80F48, ZERO_I80F48 } from '../src/numbers/I80F48'; const CLUSTER: Cluster = (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; @@ -29,6 +33,7 @@ const CLUSTER_URL = process.env.CLUSTER_URL_OVERRIDE || process.env.MB_CLUSTER_URL; const USER_KEYPAIR = process.env.USER_KEYPAIR_OVERRIDE || process.env.MB_PAYER_KEYPAIR; +const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); // eslint-disable-next-line @typescript-eslint/explicit-function-return-type (async function main() { @@ -37,7 +42,15 @@ const USER_KEYPAIR = /// const options = AnchorProvider.defaultOptions(); const connection = new Connection(CLUSTER_URL!, options); - const user = Keypair.fromSecretKey(Buffer.from(JSON.parse(USER_KEYPAIR!))); + const user = Keypair.fromSecretKey( + Buffer.from( + JSON.parse( + fs.readFileSync(USER_KEYPAIR!, { + encoding: 'utf-8', + }), + ), + ), + ); const userWallet = new Wallet(user); const userProvider = new AnchorProvider(connection, userWallet, options); const client = await MangoClient.connect( @@ -49,13 +62,15 @@ const USER_KEYPAIR = }, ); - const group = await client.getGroup(new PublicKey('MANGO_V4_MAIN_GROUP')); + const group = await client.getGroup(new PublicKey(GROUP)); await group.reloadAll(client); /// /// Prepare all oracles we want to crank /// + // TODO reload group once in a while + // oracles for tokens const oracles1 = Array.from(group.banksMapByName.values()) .filter( @@ -75,11 +90,11 @@ const USER_KEYPAIR = }); // oracles for perp markets - const oracles2 = Array.from(group.perpMarketsMapByName.values()).map((b) => { + const oracles2 = Array.from(group.perpMarketsMapByName.values()).map((pM) => { return { - oraclePk: b[0].oracle, - oracleConfig: b[0].oracleConfig, - name: b[0].name, + oraclePk: pM.oracle, + oracleConfig: pM.oracleConfig, + name: pM.name, }; }); @@ -106,6 +121,16 @@ const USER_KEYPAIR = /// Manually exclude some // TODO + /// Manually include some + oracles.push({ + oraclePk: new PublicKey('EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf'), + oracleConfig: { + confFilter: I80F48.fromString('0.1'), + maxStalenessSlots: new BN(5), + }, + name: 'BTC/USD', + }); + /// Maybe support more than one mango group // TODO @@ -128,9 +153,19 @@ const USER_KEYPAIR = /// /// sb /// - const idl = await Program.fetchIdl(SB_ON_DEMAND_PID, client.program.provider); - const sbOnDemandProgram = new Program(idl!, client.program.provider); - const queue = new PublicKey('A43DyUGA7s8eXPxqEjJY6EBu1KKbNgfxF8h17VAHn13w'); + const idl = await Anchor30Program.fetchIdl( + SB_ON_DEMAND_PID, + client.program.provider, + ); + const sbOnDemandProgram = new Anchor30Program(idl!, client.program.provider); + let queue = new PublicKey('A43DyUGA7s8eXPxqEjJY6EBu1KKbNgfxF8h17VAHn13w'); + if (CLUSTER == 'devnet') { + queue = new PublicKey('FfD96yeXs4cxZshoPPSKhSPgVQxLAJUT3gefgh84m1Di'); + } + const crossbarClient = new CrossbarClient( + 'https://crossbar.switchboard.xyz', + /* verbose= */ true, + ); /// /// Loop indefinitely @@ -167,14 +202,45 @@ const USER_KEYPAIR = } // 2. variance - // TODO - const varianceThresholdCrossedOracles = []; + const varianceThresholdCrossedOracles = new Array<{ + oracle: { + oraclePk: PublicKey; + oracleConfig: OracleConfig; + }; + ai: AccountInfo | null; + }>(); + for (const item of filteredOracles) { + const res = await parseSwitchboardOracle( + item.oracle.oraclePk, + item.ai!, + client.connection, + ); + + const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( + 'pullFeedAccountData', + item.ai!.data, + ); + + const crossBarSim = await crossbarClient.simulateFeeds([ + new Buffer(decodedPullFeed.feedHash).toString('hex'), + ]); + + const simPrice = + crossBarSim[0].results.reduce((a, b) => a + b, 0) / + crossBarSim[0].results.length; + + if ((res.price - simPrice) / res.price > 0.01) { + varianceThresholdCrossedOracles.push(item); + } + } // 3. stale or variance // TODO verify this works - const oraclesToCrank = intersection( - staleOracles, - varianceThresholdCrossedOracles, + const oraclesToCrank = uniq( + [...staleOracles, ...varianceThresholdCrossedOracles], + function (item) { + return item.oracle.oraclePk.toString(); + }, ); /// Build pull ixs @@ -188,7 +254,7 @@ const USER_KEYPAIR = const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( 'pullFeedAccountData', - oraclesToCrank.ai.data, + oracle.ai.data, ); const conf = { @@ -229,4 +295,4 @@ const USER_KEYPAIR = await new Promise((r) => setTimeout(r, 5000)); } -}); +})(); diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index 4efd3dd52..f136ba81d 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -1,10 +1,12 @@ -import { AnchorProvider, Program, Wallet } from '@coral-xyz/anchor'; +import { AnchorProvider, Wallet } from '@coral-xyz/anchor'; import { Magic as PythMagic } from '@pythnetwork/client'; import { AccountInfo, Connection, Keypair, PublicKey } from '@solana/web3.js'; import { SB_ON_DEMAND_PID } from '@switchboard-xyz/on-demand'; import SwitchboardProgram from '@switchboard-xyz/sbv2-lite'; import Big from 'big.js'; import BN from 'bn.js'; +import { Program as Anchor30Program } from 'switchboard-anchor'; + import { I80F48, I80F48Dto } from '../numbers/I80F48'; const SBV1_DEVNET_PID = new PublicKey( @@ -161,8 +163,8 @@ export async function parseSwitchboardOracle( new Wallet(new Keypair()), options, ); - const idl = await Program.fetchIdl(SB_ON_DEMAND_PID, provider); - sbOnDemandProgram = new Program(idl!, provider); + const idl = await Anchor30Program.fetchIdl(SB_ON_DEMAND_PID, provider); + sbOnDemandProgram = new Anchor30Program(idl!, provider); } return parseSwitchboardOnDemandOracle( sbOnDemandProgram, diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index f294f383b..90109a77d 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -1277,6 +1277,36 @@ export type MangoV4 = { ], "args": [] }, + { + "name": "tokenUpdateIndexAndRateResilient", + "accounts": [ + { + "name": "group", + "isMut": false, + "isSigner": false + }, + { + "name": "mintInfo", + "isMut": false, + "isSigner": false, + "relations": [ + "oracle", + "group" + ] + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "instructions", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, { "name": "accountCreate", "accounts": [ @@ -11133,6 +11163,9 @@ export type MangoV4 = { }, { "name": "RaydiumCLMM" + }, + { + "name": "SwitchboardOnDemand" } ] } @@ -15730,6 +15763,36 @@ export const IDL: MangoV4 = { ], "args": [] }, + { + "name": "tokenUpdateIndexAndRateResilient", + "accounts": [ + { + "name": "group", + "isMut": false, + "isSigner": false + }, + { + "name": "mintInfo", + "isMut": false, + "isSigner": false, + "relations": [ + "oracle", + "group" + ] + }, + { + "name": "oracle", + "isMut": false, + "isSigner": false + }, + { + "name": "instructions", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, { "name": "accountCreate", "accounts": [ @@ -25586,6 +25649,9 @@ export const IDL: MangoV4 = { }, { "name": "RaydiumCLMM" + }, + { + "name": "SwitchboardOnDemand" } ] } diff --git a/tsconfig.json b/tsconfig.json index 4f982d6b2..631e5ede3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,14 @@ "skipLibCheck": true, "strictNullChecks": true, "target": "esnext", + // "paths": { + // "C-v1": [ + // "node_modules/C@1.0.0" + // ], + // "C-v2": [ + // "node_modules/C@2.0.0" + // ] + // } }, "ts-node": { // these options are overrides used only by ts-node diff --git a/yarn.lock b/yarn.lock index 3af37ed3b..ac40e8967 100644 --- a/yarn.lock +++ b/yarn.lock @@ -66,7 +66,28 @@ resolved "https://registry.yarnpkg.com/@coral-xyz/anchor-errors/-/anchor-errors-0.30.1.tgz#bdfd3a353131345244546876eb4afc0e125bec30" integrity sha512-9Mkradf5yS5xiLWrl9WrpjqOrAV+/W2RQHDlbnAZBivoGpOs1ECjoDCkVk4aRG8ZdiFiB8zQEVlxf+8fKkmSfQ== -"@coral-xyz/anchor@^0.26.0", "@coral-xyz/anchor@^0.28.1-beta.2", "@coral-xyz/anchor@^0.30.0": +"@coral-xyz/anchor@^0.26.0": + version "0.26.0" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.26.0.tgz#c8e4f7177e93441afd030f22d777d54d0194d7d1" + integrity sha512-PxRl+wu5YyptWiR9F2MBHOLLibm87Z4IMUBPreX+DYBtPM+xggvcPi0KAN7+kIL4IrIhXI8ma5V0MCXxSN1pHg== + dependencies: + "@coral-xyz/borsh" "^0.26.0" + "@solana/web3.js" "^1.68.0" + base64-js "^1.5.1" + bn.js "^5.1.2" + bs58 "^4.0.1" + buffer-layout "^1.2.2" + camelcase "^6.3.0" + cross-fetch "^3.1.5" + crypto-hash "^1.3.0" + eventemitter3 "^4.0.7" + js-sha256 "^0.9.0" + pako "^2.0.3" + snake-case "^3.0.4" + superstruct "^0.15.4" + toml "^3.0.0" + +"@coral-xyz/anchor@^0.28.1-beta.2": version "0.28.1-beta.2" resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.28.1-beta.2.tgz#4ddd4b2b66af04407be47cf9524147793ec514a0" integrity sha512-xreUcOFF8+IQKWOBUrDKJbIw2ftpRVybFlEPVrbSlOBCbreCWrQ5754Gt9cHIcuBDAzearCDiBqzsGQdNgPJiw== @@ -87,7 +108,7 @@ superstruct "^0.15.4" toml "^3.0.0" -"@coral-xyz/anchor@^0.30.1": +"@coral-xyz/anchor@^0.30.0": version "0.30.1" resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.1.tgz#17f3e9134c28cd0ea83574c6bab4e410bcecec5d" integrity sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ== @@ -108,6 +129,14 @@ superstruct "^0.15.4" toml "^3.0.0" +"@coral-xyz/borsh@^0.26.0": + version "0.26.0" + resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.26.0.tgz#d054f64536d824634969e74138f9f7c52bbbc0d5" + integrity sha512-uCZ0xus0CszQPHYfWAqKS5swS1UxvePu83oOF+TWpUkedsNlg6p2p4azxZNSSqwXb9uXMFgxhuMBX9r3Xoi0vQ== + dependencies: + bn.js "^5.1.2" + buffer-layout "^1.2.0" + "@coral-xyz/borsh@^0.28.0": version "0.28.0" resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.28.0.tgz#fa368a2f2475bbf6f828f4657f40a52102e02b6d" @@ -116,7 +145,7 @@ bn.js "^5.1.2" buffer-layout "^1.2.0" -"@coral-xyz/borsh@^0.30.1": +"@coral-xyz/borsh@^0.30.0", "@coral-xyz/borsh@^0.30.1": version "0.30.1" resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.30.1.tgz#869d8833abe65685c72e9199b8688477a4f6b0e3" integrity sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ== @@ -131,6 +160,121 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" @@ -458,15 +602,15 @@ bs58 "^4.0.1" superstruct "^0.15.2" -"@solana/spl-token-group@^0.0.4": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.4.tgz#4f45d9526c96a33b9a1929a264d0aa21c7e38a2d" - integrity sha512-7+80nrEMdUKlK37V6kOe024+T7J4nNss0F8LQ9OOPYdWCCfJmsGUzVx2W3oeizZR4IHM6N4yC9v1Xqwc3BTPWw== +"@solana/spl-token-group@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.3.tgz#e47b0db49cd17c166101cc7650d50a9ee80cba13" + integrity sha512-oEHb/ATHbbzTwP1lNOhLM90lYcUgriMf7KA0L/W/t2OzBplS+5odNDRLccJ7lPstfrZLAAQXbqGGG7E27GXxQQ== dependencies: "@solana/codecs" "2.0.0-preview.2" "@solana/spl-type-length-value" "0.1.0" -"@solana/spl-token-metadata@^0.1.2", "@solana/spl-token-metadata@^0.1.4": +"@solana/spl-token-metadata@^0.1.2", "@solana/spl-token-metadata@^0.1.3": version "0.1.4" resolved "https://registry.yarnpkg.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.4.tgz#5cdc3b857a8c4a6877df24e24a8648c4132d22ba" integrity sha512-N3gZ8DlW6NWDV28+vCCDJoTqaCZiF/jDUnk3o8GRkAFzHObiR60Bs1gXHBa8zCPdvOwiG6Z3dg5pg7+RW6XNsQ== @@ -506,14 +650,14 @@ buffer "^6.0.3" "@solana/spl-token@^0.4.1": - version "0.4.6" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.4.6.tgz#eb44e5080ea7b6fc976abcb39457223211bd9076" - integrity sha512-1nCnUqfHVtdguFciVWaY/RKcQz1IF4b31jnKgAmjU9QVN1q7dRUkTEWJZgTYIEtsULjVnC9jRqlhgGN39WbKKA== + version "0.4.7" + resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.4.7.tgz#5d04969a67707e83d135b3de02216be69e31d86f" + integrity sha512-HvfieHwdGfoz09tl1Ph4uNR48pzl2oXfgMC3NeQ0v3D/Dk6ejTGNPR6xgPbPQ1qJ0ZuyNZOrHudF+GZH3dBybA== dependencies: "@solana/buffer-layout" "^4.0.0" "@solana/buffer-layout-utils" "^0.2.0" - "@solana/spl-token-group" "^0.0.4" - "@solana/spl-token-metadata" "^0.1.4" + "@solana/spl-token-group" "^0.0.3" + "@solana/spl-token-metadata" "^0.1.3" buffer "^6.0.3" "@solana/spl-type-length-value@0.1.0": @@ -545,9 +689,9 @@ superstruct "^0.14.2" "@solana/web3.js@^1.54.0", "@solana/web3.js@^1.91.1", "@solana/web3.js@^1.93.0": - version "1.93.1" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.93.1.tgz#7e1c0132b539f6515166760ebbeda0a4375f0fe3" - integrity sha512-3TzngqyzukYbuuweL1ejJJEPXmSRoOjaUsfBcfdx9RyDZtyP9av/GerV52mF6Lj2zEVkE7ZczpEP4tKJ8anxVQ== + version "1.93.2" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.93.2.tgz#d928be11dfcd0fc035ea26c1d0c67331b13668ad" + integrity sha512-U8GlrvjfheJTFNavJHb2v/CnpzoqbGKaShLJGf1cELeFUlweUrfYXc9YFX0tw8Icb4ll48vDxt/zEPQOQ29+kw== dependencies: "@babel/runtime" "^7.24.7" "@noble/curves" "^1.4.0" @@ -724,9 +868,9 @@ integrity sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q== "@types/node@>=13.7.0": - version "20.14.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.8.tgz#45c26a2a5de26c3534a9504530ddb3b27ce031ac" - integrity sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA== + version "20.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== dependencies: undici-types "~5.26.4" @@ -1479,6 +1623,35 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" +esbuild@~0.21.4: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" @@ -1777,6 +1950,11 @@ fsevents@~2.3.2: resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" @@ -1797,6 +1975,13 @@ get-func-name@^2.0.0: resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-tsconfig@^4.7.5: + version "4.7.5" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" + integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== + dependencies: + resolve-pkg-maps "^1.0.0" + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" @@ -2368,13 +2553,27 @@ node-cache@^5.1.2: dependencies: clone "2.x" -node-fetch@2.6.11, node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.7.0, "node-fetch@npm:@blockworks-foundation/node-fetch@2.6.11": +node-fetch@2.6.11, node-fetch@^2.6.1: version "2.6.11" resolved "https://registry.yarnpkg.com/@blockworks-foundation/node-fetch/-/node-fetch-2.6.11.tgz#fb536ef0e6a960e7b7993f3c1d3b3bba9bdfbc56" integrity sha512-HeDTxpIypSR4qCoqgUXGr8YL4OG1z7BbV4VhQ9iQs+pt2wV3MtqO+sQk2vXK3WDKu5C6BsbGmWE22BmIrcuOOw== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.6.1" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" @@ -2576,6 +2775,11 @@ resolve-from@^4.0.0: resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + resolve@^1.1.6: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" @@ -2803,6 +3007,26 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +"switchboard-anchor@npm:@coral-xyz/anchor@0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.0.tgz#52acdba504b0008f1026d3a4bbbcb2d4feb5c69e" + integrity sha512-qreDh5ztiRHVnCbJ+RS70NJ6aSTPBYDAgFeQ7Z5QvaT5DcDIhNyt4onOciVz2ieIE1XWePOJDDu9SbNvPGBkvQ== + dependencies: + "@coral-xyz/borsh" "^0.30.0" + "@noble/hashes" "^1.3.1" + "@solana/web3.js" "^1.68.0" + bn.js "^5.1.2" + bs58 "^4.0.1" + buffer-layout "^1.2.2" + camelcase "^6.3.0" + cross-fetch "^3.1.5" + crypto-hash "^1.3.0" + eventemitter3 "^4.0.7" + pako "^2.0.3" + snake-case "^3.0.4" + superstruct "^0.15.4" + toml "^3.0.0" + table@^6.0.9: version "6.8.0" resolved "https://registry.npmjs.org/table/-/table-6.8.0.tgz" @@ -2930,6 +3154,16 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tsx@^4.15.7: + version "4.15.7" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.15.7.tgz#69d7499196a323507c4051d2ba10753edcc057e5" + integrity sha512-u3H0iSFDZM3za+VxkZ1kywdCeHCn+8/qHQS1MNoO2sONDgD95HlWtt8aB23OzeTmFP9IU4/8bZUdg58Uu5J4cg== + dependencies: + esbuild "~0.21.4" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + tweetnacl@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" From 61fa97c5fc8bc0a2a7d3b2f20eef79a66c8c8851 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Thu, 27 Jun 2024 13:38:31 +0200 Subject: [PATCH 08/40] ts: sb on demand crank refactor Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 404 +++++++++++++----------- 1 file changed, 227 insertions(+), 177 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 387bf292f..a5e534479 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -1,4 +1,4 @@ -import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor'; +import { AnchorProvider, Wallet } from '@coral-xyz/anchor'; import { AccountInfo, Cluster, @@ -22,6 +22,7 @@ import uniq from 'lodash/uniq'; import { Program as Anchor30Program } from 'switchboard-anchor'; import { OracleConfig } from '../src/accounts/bank'; +import { Group } from '../src/accounts/group'; import { parseSwitchboardOracle } from '../src/accounts/oracle'; import { MangoClient } from '../src/client'; import { MANGO_V4_ID, MANGO_V4_MAIN_GROUP } from '../src/constants'; @@ -35,11 +36,223 @@ const USER_KEYPAIR = process.env.USER_KEYPAIR_OVERRIDE || process.env.MB_PAYER_KEYPAIR; const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type (async function main() { - /// - /// Wallet+Client setup - /// + const { group, client, connection, user } = await setupMango(); + + const { sbOnDemandProgram, crossbarClient, queue } = await setupSwitchboard( + client, + ); + + // TODO reload group once in a while + const filteredOracles = await prepareCandidateOracles(group, client); + + // eslint-disable-next-line no-constant-condition + while (true) { + const slot = await client.connection.getSlot(); + + const staleOracles = await filterForStaleOracles( + filteredOracles, + client, + slot, + ); + + const varianceThresholdCrossedOracles = + await filterForVarianceThresholdOracles( + filteredOracles, + client, + sbOnDemandProgram, + crossbarClient, + ); + + const oraclesToCrank = uniq( + [...staleOracles, ...varianceThresholdCrossedOracles], + function (item) { + return item.oracle.oraclePk.toString(); + }, + ); + + const pullIxs: TransactionInstruction[] = []; + const lutOwners: (PublicKey | Oracle)[] = []; + for (const oracle of oraclesToCrank) { + await preparePullIx(sbOnDemandProgram, oracle, queue, lutOwners, pullIxs); + } + + for (const c of chunk(pullIxs, 5)) { + const tx = await asV0Tx({ + connection, + ixs: [...c], + signers: [user], + computeUnitPrice: 200_000, + computeUnitLimitMultiple: 1.3, + lookupTables: await loadLookupTables(lutOwners), + }); + + const txOpts = { + commitment: 'processed' as Commitment, + skipPreflight: true, + maxRetries: 0, + }; + + const sim = await client.connection.simulateTransaction(tx, txOpts); + const sig = await client.connection.sendTransaction(tx, txOpts); + console.log(`updated in ${sig}`); // TODO add token names + } + + await new Promise((r) => setTimeout(r, 5000)); + } +})(); + +async function preparePullIx( + sbOnDemandProgram, + oracle: any, + queue: PublicKey, + lutOwners: (PublicKey | Oracle)[], + pullIxs: TransactionInstruction[], +) { + const pullFeed = new PullFeed( + sbOnDemandProgram as any, + new PublicKey(oracle.oracle.oraclePk), + ); + + const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( + 'pullFeedAccountData', + oracle.ai.data, + ); + + const conf = { + queue: queue, + maxVariance: decodedPullFeed.maxVariance.toNumber(), + minResponses: decodedPullFeed.minResponses, + numSignatures: 3, // TODO hardcoded + minSampleSize: decodedPullFeed.minSampleSize, + maxStaleness: decodedPullFeed.maxStaleness, + }; + const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); + + const lutOwners_ = [...responses.map((x) => x.oracle), pullFeed.pubkey]; + lutOwners.push(...lutOwners_); + pullIxs.push(pullIx!); +} + +async function filterForVarianceThresholdOracles( + filteredOracles: { + oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; + ai: AccountInfo | null; + }[], + client: MangoClient, + sbOnDemandProgram, + crossbarClient: CrossbarClient, +) { + const varianceThresholdCrossedOracles = new Array<{ + oracle: { + oraclePk: PublicKey; + oracleConfig: OracleConfig; + }; + ai: AccountInfo | null; + }>(); + for (const item of filteredOracles) { + const res = await parseSwitchboardOracle( + item.oracle.oraclePk, + item.ai!, + client.connection, + ); + + const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( + 'pullFeedAccountData', + item.ai!.data, + ); + + const crossBarSim = await crossbarClient.simulateFeeds([ + new Buffer(decodedPullFeed.feedHash).toString('hex'), + ]); + + const simPrice = + crossBarSim[0].results.reduce((a, b) => a + b, 0) / + crossBarSim[0].results.length; + + if ((res.price - simPrice) / res.price > 0.01) { + varianceThresholdCrossedOracles.push(item); + } + } + return varianceThresholdCrossedOracles; +} + +async function filterForStaleOracles( + filteredOracles: { + oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; + ai: AccountInfo | null; + }[], + client: MangoClient, + slot: number, +) { + const staleOracles = new Array<{ + oracle: { + oraclePk: PublicKey; + oracleConfig: OracleConfig; + }; + ai: AccountInfo | null; + }>(); + for (const item of filteredOracles) { + const res = await parseSwitchboardOracle( + item.oracle.oraclePk, + item.ai!, + client.connection, + ); + + if (slot > res.lastUpdatedSlot) { + if ( + slot - res.lastUpdatedSlot > + item.oracle.oracleConfig.maxStalenessSlots.toNumber() + ) { + staleOracles.push(item); + } + } + } + return staleOracles; +} + +async function prepareCandidateOracles(group: Group, client: MangoClient) { + const oracles = getOraclesForMangoGroup(group); + oracles.push(...extendOraclesManually()); + + const ais = await client.program.provider.connection.getMultipleAccountsInfo( + oracles.map((item) => item.oraclePk), + ); + for (const [idx, ai] of ais.entries()) { + if (ai == null || ai.data == null) { + throw new Error( + `AI returned null for ${oracles[idx].name} ${oracles[idx].oraclePk}!`, + ); + } + } + if (ais.length != oracles.length) { + throw new Error( + `Expected ${oracles.length}, but gMA returned ${ais.length}!`, + ); + } + + const filteredOracles = oracles + .map((o, i) => { + return { oracle: o, ai: ais[i] }; + }) + .filter((item) => item.ai?.owner.equals(SB_ON_DEMAND_PID)); + return filteredOracles; +} + +function extendOraclesManually() { + return [ + { + oraclePk: new PublicKey('EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf'), + oracleConfig: { + confFilter: I80F48.fromString('0.1'), + maxStalenessSlots: new BN(5), + }, + name: 'BTC/USD', + }, + ]; +} + +async function setupMango() { const options = AnchorProvider.defaultOptions(); const connection = new Connection(CLUSTER_URL!, options); const user = Keypair.fromSecretKey( @@ -64,13 +277,10 @@ const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); const group = await client.getGroup(new PublicKey(GROUP)); await group.reloadAll(client); + return { group, client, connection, user }; +} - /// - /// Prepare all oracles we want to crank - /// - - // TODO reload group once in a while - +function getOraclesForMangoGroup(group: Group) { // oracles for tokens const oracles1 = Array.from(group.banksMapByName.values()) .filter( @@ -117,42 +327,10 @@ const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); }) .filter((item) => !item.oraclePk.equals(PublicKey.default)); const oracles = oracles1.concat(oracles2).concat(oracles3); + return oracles; +} - /// Manually exclude some - // TODO - - /// Manually include some - oracles.push({ - oraclePk: new PublicKey('EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf'), - oracleConfig: { - confFilter: I80F48.fromString('0.1'), - maxStalenessSlots: new BN(5), - }, - name: 'BTC/USD', - }); - - /// Maybe support more than one mango group - // TODO - - /// Maybe support additional via csv env param - // TODO - - /// - /// Filter for sb on demand oracles - /// - // TODO ensure ai is not null - const ais = await client.program.provider.connection.getMultipleAccountsInfo( - oracles.map((item) => item.oraclePk), - ); - const filteredOracles = oracles - .map((o, i) => { - return { oracle: o, ai: ais[i] }; - }) - .filter((item) => item.ai?.owner.equals(SB_ON_DEMAND_PID)); - - /// - /// sb - /// +async function setupSwitchboard(client: MangoClient) { const idl = await Anchor30Program.fetchIdl( SB_ON_DEMAND_PID, client.program.provider, @@ -164,135 +342,7 @@ const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); } const crossbarClient = new CrossbarClient( 'https://crossbar.switchboard.xyz', - /* verbose= */ true, + true, ); - - /// - /// Loop indefinitely - /// - // eslint-disable-next-line no-constant-condition - while (true) { - const slot = await client.connection.getSlot(); - - // filter candidates for this iteration - - // 1. stale - const staleOracles = new Array<{ - oracle: { - oraclePk: PublicKey; - oracleConfig: OracleConfig; - }; - ai: AccountInfo | null; - }>(); - for (const item of filteredOracles) { - const res = await parseSwitchboardOracle( - item.oracle.oraclePk, - item.ai!, - client.connection, - ); - - if (slot > res.lastUpdatedSlot) { - if ( - slot - res.lastUpdatedSlot > - item.oracle.oracleConfig.maxStalenessSlots.toNumber() - ) { - staleOracles.push(item); - } - } - } - - // 2. variance - const varianceThresholdCrossedOracles = new Array<{ - oracle: { - oraclePk: PublicKey; - oracleConfig: OracleConfig; - }; - ai: AccountInfo | null; - }>(); - for (const item of filteredOracles) { - const res = await parseSwitchboardOracle( - item.oracle.oraclePk, - item.ai!, - client.connection, - ); - - const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( - 'pullFeedAccountData', - item.ai!.data, - ); - - const crossBarSim = await crossbarClient.simulateFeeds([ - new Buffer(decodedPullFeed.feedHash).toString('hex'), - ]); - - const simPrice = - crossBarSim[0].results.reduce((a, b) => a + b, 0) / - crossBarSim[0].results.length; - - if ((res.price - simPrice) / res.price > 0.01) { - varianceThresholdCrossedOracles.push(item); - } - } - - // 3. stale or variance - // TODO verify this works - const oraclesToCrank = uniq( - [...staleOracles, ...varianceThresholdCrossedOracles], - function (item) { - return item.oracle.oraclePk.toString(); - }, - ); - - /// Build pull ixs - const pullIxs: TransactionInstruction[] = []; - const lutOwners: (PublicKey | Oracle)[] = []; - for (const oracle of oraclesToCrank) { - const pullFeed = new PullFeed( - sbOnDemandProgram as any, - new PublicKey(oracle.oracle.oraclePk), - ); - - const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( - 'pullFeedAccountData', - oracle.ai.data, - ); - - const conf = { - queue: queue, - maxVariance: decodedPullFeed.maxVariance.toNumber(), - minResponses: decodedPullFeed.minResponses, - numSignatures: 3, // TODO hardcoded - minSampleSize: decodedPullFeed.minSampleSize, - maxStaleness: decodedPullFeed.maxStaleness, - }; - const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); - - const lutOwners_ = [...responses.map((x) => x.oracle), pullFeed.pubkey]; - lutOwners.push(...lutOwners_); - pullIxs.push(pullIx!); - } - - for (const c of chunk(pullIxs, 5)) { - const tx = await asV0Tx({ - connection, - ixs: [...c], - signers: [user], - computeUnitPrice: 200_000, - computeUnitLimitMultiple: 1.3, - lookupTables: await loadLookupTables(lutOwners), - }); - - const txOpts = { - commitment: 'processed' as Commitment, - skipPreflight: true, - maxRetries: 0, - }; - - const sim = await client.connection.simulateTransaction(tx, txOpts); - const sig = await client.connection.sendTransaction(tx, txOpts); - console.log(`updated in ${sig}`); // TODO add token names - } - - await new Promise((r) => setTimeout(r, 5000)); - } -})(); + return { sbOnDemandProgram, crossbarClient, queue }; +} From 140f47de9231fd55ffbd02ffb11214148bbc3b09 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Fri, 28 Jun 2024 12:21:28 +0200 Subject: [PATCH 09/40] add example Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-create-feed.ts | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 ts/client/scripts/sb-on-demand-create-feed.ts diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts new file mode 100644 index 000000000..4112a0fc4 --- /dev/null +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -0,0 +1,123 @@ +import { + Cluster, + Commitment, + Connection, + Keypair, + PublicKey, +} from '@solana/web3.js'; + +import { decodeString } from '@switchboard-xyz/common'; +import { + asV0Tx, + CrossbarClient, + PullFeed, + Queue, + SB_ON_DEMAND_PID, +} from '@switchboard-xyz/on-demand'; +import fs from 'fs'; +import { + Program as Anchor30Program, + AnchorProvider, + Wallet, +} from 'switchboard-anchor'; + +const CLUSTER: Cluster = + (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; +const CLUSTER_URL = + process.env.CLUSTER_URL_OVERRIDE || process.env.MB_CLUSTER_URL; +const USER_KEYPAIR = + process.env.USER_KEYPAIR_OVERRIDE || process.env.MB_PAYER_KEYPAIR; + +async function setupAnchor() { + const options = AnchorProvider.defaultOptions(); + const connection = new Connection(CLUSTER_URL!, options); + const user = Keypair.fromSecretKey( + Buffer.from( + JSON.parse( + fs.readFileSync(USER_KEYPAIR!, { + encoding: 'utf-8', + }), + ), + ), + ); + const userWallet = new Wallet(user); + const userProvider = new AnchorProvider(connection, userWallet, options); + + return { userProvider, connection, user }; +} + +async function setupSwitchboard(userProvider: AnchorProvider) { + const idl = await Anchor30Program.fetchIdl(SB_ON_DEMAND_PID, userProvider); + const sbOnDemandProgram = new Anchor30Program(idl!, userProvider); + let queue = new PublicKey('A43DyUGA7s8eXPxqEjJY6EBu1KKbNgfxF8h17VAHn13w'); + if (CLUSTER == 'devnet') { + queue = new PublicKey('FfD96yeXs4cxZshoPPSKhSPgVQxLAJUT3gefgh84m1Di'); + } + const crossbarClient = new CrossbarClient( + 'https://crossbar.switchboard.xyz', + true, + ); + return { sbOnDemandProgram, crossbarClient, queue }; +} + +(async function main(): Promise { + const { userProvider, connection, user } = await setupAnchor(); + + const { sbOnDemandProgram, crossbarClient, queue } = await setupSwitchboard( + userProvider, + ); + + const queueAccount = new Queue(sbOnDemandProgram, queue); + try { + await queueAccount.loadData(); + } catch (err) { + console.error('Queue not found, ensure you are using devnet in your env'); + return; + } + + const txOpts = { + commitment: 'processed' as Commitment, + skipPreflight: true, + maxRetries: 0, + }; + + // TODO @Adrian + const conf = { + name: 'BTC Price Feed', // the feed name (max 32 bytes) + queue, // the queue of oracles to bind to + maxVariance: 1.0, // allow 1% variance between submissions and jobs + minResponses: 1, // minimum number of responses of jobs to allow + numSignatures: 3, // number of signatures to fetch per update + minSampleSize: 1, // minimum number of responses to sample + maxStaleness: 60, // maximum staleness of responses in seconds to sample + }; + + console.log('Initializing new data feed'); + // Generate the feed keypair + const [pullFeed, feedKp] = PullFeed.generate(sbOnDemandProgram); + const jobs = [ + // TODO @Adrian + // source https://github.com/switchboard-xyz/sb-on-demand-examples/blob/main/sb-on-demand-feeds/scripts/utils.ts#L23 + // buildPythnetJob( + // 'e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43', + // ), + // buildCoinbaseJob('BTC-USD'), + ]; + const decodedFeedHash = await crossbarClient + .store(queue.toBase58(), jobs) + .then((resp) => decodeString(resp.feedHash)); + console.log('Feed hash:', decodedFeedHash); + + const tx = await asV0Tx({ + connection: sbOnDemandProgram.provider.connection, + ixs: [await pullFeed.initIx({ ...conf, feedHash: decodedFeedHash! })], + payer: user.publicKey, + signers: [user, feedKp], + computeUnitPrice: 75_000, + computeUnitLimitMultiple: 1.3, + }); + console.log('Sending initialize transaction'); + const sim = await connection.simulateTransaction(tx, txOpts); + const sig = await connection.sendTransaction(tx, txOpts); + console.log(`Feed ${feedKp.publicKey} initialized: ${sig}`); +})(); From d5fdb0a4f1ca4d64b1fde0cf6126fa1c5ca15dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Brzezin=CC=81ski?= Date: Fri, 28 Jun 2024 13:28:38 +0200 Subject: [PATCH 10/40] add job --- ts/client/scripts/sb-on-demand-create-feed.ts | 176 +++++++++++++++++- 1 file changed, 169 insertions(+), 7 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index 4112a0fc4..c20fadfdc 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -10,6 +10,7 @@ import { decodeString } from '@switchboard-xyz/common'; import { asV0Tx, CrossbarClient, + OracleJob, PullFeed, Queue, SB_ON_DEMAND_PID, @@ -20,7 +21,18 @@ import { AnchorProvider, Wallet, } from 'switchboard-anchor'; +//basic configuration +const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; +const SWAP_VALUE = '100'; +const TOKEN_MINT = 'SLCLww7nc1PD2gQPQdGayHviVVcpMthnqUz2iWKhNQV'; +const FALLBACK_POOL_NAME: 'orcaPoolAddress' | 'raydiumPoolAddress' = + 'raydiumPoolAddress'; +const FALLBACK_POOL = '5hbCYGfGGenjeYzfWGFZ8zoXTo3fcHw5KkdsnXpXdbeX'; +const TOKEN_SYMBOL = 'SLCL'; +//basic configuration +const pythUsdOracle = 'Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD'; +const switchboardUsdDaoOracle = 'FwYfsmj5x8YZXtQBNo2Cz8TE7WRCMFqA6UTffK4xQKMH'; const CLUSTER: Cluster = (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; const CLUSTER_URL = @@ -83,7 +95,7 @@ async function setupSwitchboard(userProvider: AnchorProvider) { // TODO @Adrian const conf = { - name: 'BTC Price Feed', // the feed name (max 32 bytes) + name: `${TOKEN_SYMBOL}/USD`, // the feed name (max 32 bytes) queue, // the queue of oracles to bind to maxVariance: 1.0, // allow 1% variance between submissions and jobs minResponses: 1, // minimum number of responses of jobs to allow @@ -96,12 +108,162 @@ async function setupSwitchboard(userProvider: AnchorProvider) { // Generate the feed keypair const [pullFeed, feedKp] = PullFeed.generate(sbOnDemandProgram); const jobs = [ - // TODO @Adrian - // source https://github.com/switchboard-xyz/sb-on-demand-examples/blob/main/sb-on-demand-feeds/scripts/utils.ts#L23 - // buildPythnetJob( - // 'e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43', - // ), - // buildCoinbaseJob('BTC-USD'), + OracleJob.fromObject({ + tasks: [ + { + conditionalTask: { + attempt: [ + { + valueTask: { + big: SWAP_VALUE, + }, + }, + { + divideTask: { + job: { + tasks: [ + { + jupiterSwapTask: { + inTokenAddress: USDC_MINT, + outTokenAddress: TOKEN_MINT, + baseAmountString: SWAP_VALUE, + }, + }, + ], + }, + }, + }, + ], + onFailure: [ + { + lpExchangeRateTask: { + [FALLBACK_POOL_NAME]: FALLBACK_POOL, + }, + }, + ], + }, + }, + { + conditionalTask: { + attempt: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + pythAddress: pythUsdOracle, + pythAllowedConfidenceInterval: 10, + }, + }, + ], + }, + }, + }, + ], + onFailure: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + switchboardAddress: switchboardUsdDaoOracle, + }, + }, + ], + }, + }, + }, + ], + }, + }, + ], + }), + OracleJob.fromObject({ + tasks: [ + { + conditionalTask: { + attempt: [ + { + cacheTask: { + cacheItems: [ + { + variableName: 'QTY', + job: { + tasks: [ + { + jupiterSwapTask: { + inTokenAddress: USDC_MINT, + outTokenAddress: TOKEN_MINT, + baseAmountString: SWAP_VALUE, + }, + }, + ], + }, + }, + ], + }, + }, + { + jupiterSwapTask: { + inTokenAddress: TOKEN_MINT, + outTokenAddress: USDC_MINT, + baseAmountString: '${QTY}', + }, + }, + { + divideTask: { + big: '${QTY}', + }, + }, + ], + onFailure: [ + { + lpExchangeRateTask: { + [FALLBACK_POOL_NAME]: FALLBACK_POOL, + }, + }, + ], + }, + }, + { + conditionalTask: { + attempt: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + pythAddress: pythUsdOracle, + pythAllowedConfidenceInterval: 10, + }, + }, + ], + }, + }, + }, + ], + onFailure: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + switchboardAddress: switchboardUsdDaoOracle, + }, + }, + ], + }, + }, + }, + ], + }, + }, + ], + }), ]; const decodedFeedHash = await crossbarClient .store(queue.toBase58(), jobs) From e2841d72fc9a188d9bd160fae1ac21c101bfe0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Brzezin=CC=81ski?= Date: Fri, 28 Jun 2024 13:30:21 +0200 Subject: [PATCH 11/40] min 2 resp --- ts/client/scripts/sb-on-demand-create-feed.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index c20fadfdc..5b10b9da0 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -98,7 +98,7 @@ async function setupSwitchboard(userProvider: AnchorProvider) { name: `${TOKEN_SYMBOL}/USD`, // the feed name (max 32 bytes) queue, // the queue of oracles to bind to maxVariance: 1.0, // allow 1% variance between submissions and jobs - minResponses: 1, // minimum number of responses of jobs to allow + minResponses: 2, // minimum number of responses of jobs to allow numSignatures: 3, // number of signatures to fetch per update minSampleSize: 1, // minimum number of responses to sample maxStaleness: 60, // maximum staleness of responses in seconds to sample From 95ba57627e90f4bd073f0f5fbc294fe81c11329c Mon Sep 17 00:00:00 2001 From: Riordan Panayides Date: Fri, 28 Jun 2024 14:52:58 +0100 Subject: [PATCH 12/40] add deployment config for sb-on-demand-crank, fix BN import --- cd/switchboard-crank.toml | 13 +++++++++++++ ts/client/scripts/Dockerfile.scripts | 22 ++++++++++++++++++++++ ts/client/scripts/sb-on-demand-crank.ts | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 cd/switchboard-crank.toml create mode 100644 ts/client/scripts/Dockerfile.scripts diff --git a/cd/switchboard-crank.toml b/cd/switchboard-crank.toml new file mode 100644 index 000000000..f2f79d525 --- /dev/null +++ b/cd/switchboard-crank.toml @@ -0,0 +1,13 @@ +app = "switchboard-crank" +kill_signal = "SIGINT" +kill_timeout = 5 + +[build] + dockerfile = "../ts/client/scripts/Dockerfile.scripts" + +[experimental] + cmd = ["yarn", "tsx", "ts/client/scripts/sb-on-demand-crank.ts"] + +[[vm]] + size = "shared-cpu-1x" + memory = "512mb" diff --git a/ts/client/scripts/Dockerfile.scripts b/ts/client/scripts/Dockerfile.scripts new file mode 100644 index 000000000..93bfacebc --- /dev/null +++ b/ts/client/scripts/Dockerfile.scripts @@ -0,0 +1,22 @@ +FROM node:18 as builder + +WORKDIR /app + +COPY package.json yarn.lock ./ +RUN yarn install + +COPY ts ts + +RUN ls + +# scripts are run with tsx, no upfront build needed +# RUN yarn build + +FROM node:18-slim as run + +LABEL fly_launch_runtime="nodejs" + +COPY --from=builder /app /app + +WORKDIR /app +ENV NODE_ENV production \ No newline at end of file diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index a5e534479..c8cac4d13 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -1,4 +1,4 @@ -import { AnchorProvider, Wallet } from '@coral-xyz/anchor'; +import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor'; import { AccountInfo, Cluster, From 737977f45efc5e909da1fdeebf614bcf1be16eab Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Fri, 28 Jun 2024 16:39:47 +0200 Subject: [PATCH 13/40] ts: update to on demand code Signed-off-by: microwavedcola1 --- package.json | 2 +- ts/client/scripts/sb-on-demand-crank.ts | 176 +++++++++++------- ts/client/scripts/sb-on-demand-create-feed.ts | 24 ++- ts/client/src/accounts/oracle.ts | 17 +- yarn.lock | 24 +-- 5 files changed, 140 insertions(+), 103 deletions(-) diff --git a/package.json b/package.json index cb99b2f02..d045ac783 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "fast-copy": "^3.0.1", "lodash": "^4.17.21", "node-kraken-api": "^2.2.2", - "switchboard-anchor": "npm:@coral-xyz/anchor@0.30.0" + "switchboard-anchor": "npm:@coral-xyz/anchor@0.30.1" }, "license": "MIT", "packageManager": "yarn@4.3.1" diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index c8cac4d13..43a83bb7b 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -18,7 +18,7 @@ import { } from '@switchboard-xyz/on-demand'; import fs from 'fs'; import chunk from 'lodash/chunk'; -import uniq from 'lodash/uniq'; +import uniqWith from 'lodash/uniqWith'; import { Program as Anchor30Program } from 'switchboard-anchor'; import { OracleConfig } from '../src/accounts/bank'; @@ -43,62 +43,72 @@ const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); client, ); - // TODO reload group once in a while - const filteredOracles = await prepareCandidateOracles(group, client); - // eslint-disable-next-line no-constant-condition while (true) { - const slot = await client.connection.getSlot(); + try { + const filteredOracles = await prepareCandidateOracles(group, client); + for (let i = 0; i < 10; i++) { + const slot = await client.connection.getSlot(); - const staleOracles = await filterForStaleOracles( - filteredOracles, - client, - slot, - ); + const staleOracles = await filterForStaleOracles( + filteredOracles, + client, + slot, + ); - const varianceThresholdCrossedOracles = - await filterForVarianceThresholdOracles( - filteredOracles, - client, - sbOnDemandProgram, - crossbarClient, - ); + const varianceThresholdCrossedOracles = + await filterForVarianceThresholdOracles( + filteredOracles, + client, + sbOnDemandProgram, + crossbarClient, + ); - const oraclesToCrank = uniq( - [...staleOracles, ...varianceThresholdCrossedOracles], - function (item) { - return item.oracle.oraclePk.toString(); - }, - ); + const oraclesToCrank = uniqWith( + [...staleOracles, ...varianceThresholdCrossedOracles], + function (item) { + return item.oracle.oraclePk.toString(); + }, + ); - const pullIxs: TransactionInstruction[] = []; - const lutOwners: (PublicKey | Oracle)[] = []; - for (const oracle of oraclesToCrank) { - await preparePullIx(sbOnDemandProgram, oracle, queue, lutOwners, pullIxs); + const pullIxs: TransactionInstruction[] = []; + const lutOwners: (PublicKey | Oracle)[] = []; + for (const oracle of oraclesToCrank) { + await preparePullIx( + sbOnDemandProgram, + oracle, + queue, + lutOwners, + pullIxs, + ); + } + + for (const c of chunk(pullIxs, 5, false)) { + const tx = await asV0Tx({ + connection, + ixs: [...c], + signers: [user], + computeUnitPrice: 200_000, + computeUnitLimitMultiple: 1.3, + lookupTables: await loadLookupTables(lutOwners), + }); + + const txOpts = { + commitment: 'processed' as Commitment, + skipPreflight: true, + maxRetries: 0, + }; + + const sim = await client.connection.simulateTransaction(tx, txOpts); + const sig = await client.connection.sendTransaction(tx, txOpts); + console.log(`updated in ${sig}`); // TODO add token names + } + + await new Promise((r) => setTimeout(r, 5000)); + } + } catch (error) { + console.log(error); } - - for (const c of chunk(pullIxs, 5)) { - const tx = await asV0Tx({ - connection, - ixs: [...c], - signers: [user], - computeUnitPrice: 200_000, - computeUnitLimitMultiple: 1.3, - lookupTables: await loadLookupTables(lutOwners), - }); - - const txOpts = { - commitment: 'processed' as Commitment, - skipPreflight: true, - maxRetries: 0, - }; - - const sim = await client.connection.simulateTransaction(tx, txOpts); - const sig = await client.connection.sendTransaction(tx, txOpts); - console.log(`updated in ${sig}`); // TODO add token names - } - - await new Promise((r) => setTimeout(r, 5000)); } })(); @@ -123,12 +133,17 @@ async function preparePullIx( queue: queue, maxVariance: decodedPullFeed.maxVariance.toNumber(), minResponses: decodedPullFeed.minResponses, - numSignatures: 3, // TODO hardcoded - minSampleSize: decodedPullFeed.minSampleSize, - maxStaleness: decodedPullFeed.maxStaleness, + numSignatures: 1, + // TODO: I think these are not required + // minSampleSize: decodedPullFeed.minSampleSize, + // maxStaleness: decodedPullFeed.maxStaleness, }; const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); + if (pullIx === undefined) { + return; + } + const lutOwners_ = [...responses.map((x) => x.oracle), pullFeed.pubkey]; lutOwners.push(...lutOwners_); pullIxs.push(pullIx!); @@ -171,7 +186,14 @@ async function filterForVarianceThresholdOracles( crossBarSim[0].results.length; if ((res.price - simPrice) / res.price > 0.01) { + console.log( + `- Variance threshold crossed oracles candidate ${item.oracle.name}`, + ); varianceThresholdCrossedOracles.push(item); + } else { + console.log( + `- Variance threshold crossed oracles non candidate ${item.oracle.name}`, + ); } } return varianceThresholdCrossedOracles; @@ -200,12 +222,15 @@ async function filterForStaleOracles( ); if (slot > res.lastUpdatedSlot) { + console.log(`- Stale oracle candidate ${item.oracle.name}`); if ( slot - res.lastUpdatedSlot > item.oracle.oracleConfig.maxStalenessSlots.toNumber() ) { staleOracles.push(item); } + } else { + console.log(`- Stale oracle non candidate ${item.oracle.name}`); } } return staleOracles; @@ -213,11 +238,23 @@ async function filterForStaleOracles( async function prepareCandidateOracles(group: Group, client: MangoClient) { const oracles = getOraclesForMangoGroup(group); - oracles.push(...extendOraclesManually()); + oracles.push(...extendOraclesManually(CLUSTER)); + + const ais = ( + await Promise.all( + chunk( + oracles.map((item) => item.oraclePk), + 50, + false, + ).map( + async (chunk) => + await client.program.provider.connection.getMultipleAccountsInfo( + chunk, + ), + ), + ) + ).flat(); - const ais = await client.program.provider.connection.getMultipleAccountsInfo( - oracles.map((item) => item.oraclePk), - ); for (const [idx, ai] of ais.entries()) { if (ai == null || ai.data == null) { throw new Error( @@ -239,15 +276,28 @@ async function prepareCandidateOracles(group: Group, client: MangoClient) { return filteredOracles; } -function extendOraclesManually() { +function extendOraclesManually(cluster: Cluster) { + if (cluster == 'devnet') { + return [ + { + oraclePk: new PublicKey('EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf'), + oracleConfig: { + confFilter: I80F48.fromString('0.1'), + maxStalenessSlots: new BN(5), + }, + name: 'BTC/USD', + }, + ]; + } return [ { - oraclePk: new PublicKey('EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf'), + // https://ondemand.switchboard.xyz/solana/mainnet/user/8SSLjXBEVk9nesbhi9UMCA32uijbVBUqWoKPPQPTekzt/ + oraclePk: new PublicKey('EFSBitmy2LZexy6CqYVDAqzWN6wYHZmHkFZxmUjNgwpb'), oracleConfig: { - confFilter: I80F48.fromString('0.1'), - maxStalenessSlots: new BN(5), + confFilter: I80F48.fromString('1000'), + maxStalenessSlots: new BN(-1), }, - name: 'BTC/USD', + name: 'MNGO/USD', }, ]; } @@ -342,7 +392,7 @@ async function setupSwitchboard(client: MangoClient) { } const crossbarClient = new CrossbarClient( 'https://crossbar.switchboard.xyz', - true, + false, ); return { sbOnDemandProgram, crossbarClient, queue }; } diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index 5b10b9da0..d279ae325 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -1,3 +1,4 @@ +import { LISTING_PRESETS } from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools'; import { Cluster, Commitment, @@ -21,15 +22,15 @@ import { AnchorProvider, Wallet, } from 'switchboard-anchor'; -//basic configuration +// basic configuration const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; const SWAP_VALUE = '100'; -const TOKEN_MINT = 'SLCLww7nc1PD2gQPQdGayHviVVcpMthnqUz2iWKhNQV'; +const TOKEN_MINT = 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac'; const FALLBACK_POOL_NAME: 'orcaPoolAddress' | 'raydiumPoolAddress' = 'raydiumPoolAddress'; -const FALLBACK_POOL = '5hbCYGfGGenjeYzfWGFZ8zoXTo3fcHw5KkdsnXpXdbeX'; -const TOKEN_SYMBOL = 'SLCL'; -//basic configuration +const FALLBACK_POOL = '34tFULRrRwh4bMcBLPtJaNqqe5pVgGZACi5sR8Xz95KC'; +const TOKEN_SYMBOL = 'MNGO'; +// basic configuration const pythUsdOracle = 'Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD'; const switchboardUsdDaoOracle = 'FwYfsmj5x8YZXtQBNo2Cz8TE7WRCMFqA6UTffK4xQKMH'; @@ -73,6 +74,10 @@ async function setupSwitchboard(userProvider: AnchorProvider) { } (async function main(): Promise { + const tier = Object.values(LISTING_PRESETS).find( + (x) => x.preset_name === 'C', + ); + const { userProvider, connection, user } = await setupAnchor(); const { sbOnDemandProgram, crossbarClient, queue } = await setupSwitchboard( @@ -93,15 +98,14 @@ async function setupSwitchboard(userProvider: AnchorProvider) { maxRetries: 0, }; - // TODO @Adrian const conf = { name: `${TOKEN_SYMBOL}/USD`, // the feed name (max 32 bytes) queue, // the queue of oracles to bind to - maxVariance: 1.0, // allow 1% variance between submissions and jobs - minResponses: 2, // minimum number of responses of jobs to allow - numSignatures: 3, // number of signatures to fetch per update + maxVariance: 10, // allow 1% variance between submissions and jobs + minResponses: 1, // minimum number of responses of jobs to allow + numSignatures: 1, // number of signatures to fetch per update minSampleSize: 1, // minimum number of responses to sample - maxStaleness: 60, // maximum staleness of responses in seconds to sample + maxStaleness: tier!.maxStalenessSlots!, // maximum staleness of responses in seconds to sample }; console.log('Initializing new data feed'); diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index f136ba81d..ae0bab990 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -1,7 +1,7 @@ import { AnchorProvider, Wallet } from '@coral-xyz/anchor'; import { Magic as PythMagic } from '@pythnetwork/client'; import { AccountInfo, Connection, Keypair, PublicKey } from '@solana/web3.js'; -import { SB_ON_DEMAND_PID } from '@switchboard-xyz/on-demand'; +import { SB_ON_DEMAND_PID, toFeedValue } from '@switchboard-xyz/on-demand'; import SwitchboardProgram from '@switchboard-xyz/sbv2-lite'; import Big from 'big.js'; import BN from 'bn.js'; @@ -130,16 +130,19 @@ export function parseSwitchboardOnDemandOracle( accountInfo.data, ); - // This code was used when decodedPullFeed.result used to be empty - // const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); - // const price = new Big(feedValue?.value.toString()).div(1e18); - // const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! - // const stdDeviation = 0; // TODO the 0 + if (decodedPullFeed.result == undefined) { + const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); + console.log(decodedPullFeed.submissions); + console.log(feedValue); + const price = new Big(feedValue?.value.toString()).div(1e18); + const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! + const stdDeviation = 0; // TODO the 0 + return { price, lastUpdatedSlot, uiDeviation: stdDeviation }; + } const price = new Big(decodedPullFeed.result.value.toString()).div(1e18); const lastUpdatedSlot = decodedPullFeed.result.slot.toNumber(); const stdDeviation = decodedPullFeed.result.stdDev.toNumber(); - return { price, lastUpdatedSlot, uiDeviation: stdDeviation }; } catch (e) { console.log( diff --git a/yarn.lock b/yarn.lock index ac40e8967..2b3281e22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -108,7 +108,7 @@ superstruct "^0.15.4" toml "^3.0.0" -"@coral-xyz/anchor@^0.30.0": +"@coral-xyz/anchor@^0.30.0", "switchboard-anchor@npm:@coral-xyz/anchor@0.30.1": version "0.30.1" resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.1.tgz#17f3e9134c28cd0ea83574c6bab4e410bcecec5d" integrity sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ== @@ -145,7 +145,7 @@ bn.js "^5.1.2" buffer-layout "^1.2.0" -"@coral-xyz/borsh@^0.30.0", "@coral-xyz/borsh@^0.30.1": +"@coral-xyz/borsh@^0.30.1": version "0.30.1" resolved "https://registry.yarnpkg.com/@coral-xyz/borsh/-/borsh-0.30.1.tgz#869d8833abe65685c72e9199b8688477a4f6b0e3" integrity sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ== @@ -3007,26 +3007,6 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -"switchboard-anchor@npm:@coral-xyz/anchor@0.30.0": - version "0.30.0" - resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.0.tgz#52acdba504b0008f1026d3a4bbbcb2d4feb5c69e" - integrity sha512-qreDh5ztiRHVnCbJ+RS70NJ6aSTPBYDAgFeQ7Z5QvaT5DcDIhNyt4onOciVz2ieIE1XWePOJDDu9SbNvPGBkvQ== - dependencies: - "@coral-xyz/borsh" "^0.30.0" - "@noble/hashes" "^1.3.1" - "@solana/web3.js" "^1.68.0" - bn.js "^5.1.2" - bs58 "^4.0.1" - buffer-layout "^1.2.2" - camelcase "^6.3.0" - cross-fetch "^3.1.5" - crypto-hash "^1.3.0" - eventemitter3 "^4.0.7" - pako "^2.0.3" - snake-case "^3.0.4" - superstruct "^0.15.4" - toml "^3.0.0" - table@^6.0.9: version "6.8.0" resolved "https://registry.npmjs.org/table/-/table-6.8.0.tgz" From f7f9894c12a92303c805f945b7c9591a0613c7f3 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Fri, 28 Jun 2024 17:06:18 +0200 Subject: [PATCH 14/40] ts: update sb on demand Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 6 ++---- ts/client/scripts/sb-on-demand-create-feed.ts | 8 ++++---- ts/client/src/accounts/oracle.ts | 2 -- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 43a83bb7b..6c3e33a35 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -292,7 +292,7 @@ function extendOraclesManually(cluster: Cluster) { return [ { // https://ondemand.switchboard.xyz/solana/mainnet/user/8SSLjXBEVk9nesbhi9UMCA32uijbVBUqWoKPPQPTekzt/ - oraclePk: new PublicKey('EFSBitmy2LZexy6CqYVDAqzWN6wYHZmHkFZxmUjNgwpb'), + oraclePk: new PublicKey('Hrp9Lq2zcSPAtuKCsukrVhawKMWVktfWKPVtLYwveAtu'), oracleConfig: { confFilter: I80F48.fromString('1000'), maxStalenessSlots: new BN(-1), @@ -308,9 +308,7 @@ async function setupMango() { const user = Keypair.fromSecretKey( Buffer.from( JSON.parse( - fs.readFileSync(USER_KEYPAIR!, { - encoding: 'utf-8', - }), + process.env.KEYPAIR || fs.readFileSync(USER_KEYPAIR!, 'utf-8'), ), ), ); diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index d279ae325..178f12d4c 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -93,7 +93,7 @@ async function setupSwitchboard(userProvider: AnchorProvider) { } const txOpts = { - commitment: 'processed' as Commitment, + commitment: 'finalized' as Commitment, skipPreflight: true, maxRetries: 0, }; @@ -102,9 +102,9 @@ async function setupSwitchboard(userProvider: AnchorProvider) { name: `${TOKEN_SYMBOL}/USD`, // the feed name (max 32 bytes) queue, // the queue of oracles to bind to maxVariance: 10, // allow 1% variance between submissions and jobs - minResponses: 1, // minimum number of responses of jobs to allow - numSignatures: 1, // number of signatures to fetch per update - minSampleSize: 1, // minimum number of responses to sample + minResponses: 2, // minimum number of responses of jobs to allow + numSignatures: 3, // number of signatures to fetch per update + minSampleSize: 2, // minimum number of responses to sample maxStaleness: tier!.maxStalenessSlots!, // maximum staleness of responses in seconds to sample }; diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index ae0bab990..5d6d05f35 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -132,8 +132,6 @@ export function parseSwitchboardOnDemandOracle( if (decodedPullFeed.result == undefined) { const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); - console.log(decodedPullFeed.submissions); - console.log(feedValue); const price = new Big(feedValue?.value.toString()).div(1e18); const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! const stdDeviation = 0; // TODO the 0 From 3f32ddac8879c29014af216e40cadd41bcc9f2b0 Mon Sep 17 00:00:00 2001 From: Serge Farny Date: Tue, 2 Jul 2024 18:30:34 +0200 Subject: [PATCH 15/40] Program: housekeeping --- programs/mango-v4/src/state/oracle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/mango-v4/src/state/oracle.rs b/programs/mango-v4/src/state/oracle.rs index 23fb64ece..34d55b688 100644 --- a/programs/mango-v4/src/state/oracle.rs +++ b/programs/mango-v4/src/state/oracle.rs @@ -443,7 +443,7 @@ fn oracle_state_unchecked_inner( require_gte!(price, 0); OracleState { price, - last_update_slot: last_update_slot, + last_update_slot, deviation, oracle_type: OracleType::SwitchboardOnDemand, } From c7ed75fee69477f724ebcec8c279e7cdf7e6789e Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Wed, 3 Jul 2024 08:59:28 +0200 Subject: [PATCH 16/40] update Signed-off-by: microwavedcola1 --- package.json | 2 +- ts/client/scripts/sb-on-demand-crank.ts | 91 +++++++++++++++---- ts/client/scripts/sb-on-demand-create-feed.ts | 7 +- ts/client/src/accounts/oracle.ts | 3 + yarn.lock | 42 +++------ 5 files changed, 94 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index d045ac783..d2b786e3c 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@pythnetwork/client": "~2.14.0", "@solana/spl-token": "0.3.7", "@solana/web3.js": "^1.78.2", - "@switchboard-xyz/on-demand": "^1.1.24", + "@switchboard-xyz/on-demand": "^1.1.26", "@switchboard-xyz/sbv2-lite": "^0.1.6", "big.js": "^6.1.1", "binance-api-node": "^0.12.0", diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 6c3e33a35..71271b5bb 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -1,4 +1,3 @@ -import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor'; import { AccountInfo, Cluster, @@ -21,6 +20,8 @@ import chunk from 'lodash/chunk'; import uniqWith from 'lodash/uniqWith'; import { Program as Anchor30Program } from 'switchboard-anchor'; +import BN from 'bn.js'; +import { AnchorProvider, Wallet } from 'switchboard-anchor'; import { OracleConfig } from '../src/accounts/bank'; import { Group } from '../src/accounts/group'; import { parseSwitchboardOracle } from '../src/accounts/oracle'; @@ -35,8 +36,11 @@ const CLUSTER_URL = const USER_KEYPAIR = process.env.USER_KEYPAIR_OVERRIDE || process.env.MB_PAYER_KEYPAIR; const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); +const SLEEP_MS = Number(process.env.SLEEP_MS) || 5_000; -(async function main() { +// TODO use mangolana to send txs + +(async function main(): Promise { const { group, client, connection, user } = await setupMango(); const { sbOnDemandProgram, crossbarClient, queue } = await setupSwitchboard( @@ -46,10 +50,14 @@ const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); // eslint-disable-next-line no-constant-condition while (true) { try { + // periodically check if we have new candidates on the group const filteredOracles = await prepareCandidateOracles(group, client); + for (let i = 0; i < 10; i++) { const slot = await client.connection.getSlot(); + await updateFilteredOraclesAis(client.connection, filteredOracles); + const staleOracles = await filterForStaleOracles( filteredOracles, client, @@ -99,12 +107,11 @@ const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); maxRetries: 0, }; - const sim = await client.connection.simulateTransaction(tx, txOpts); const sig = await client.connection.sendTransaction(tx, txOpts); - console.log(`updated in ${sig}`); // TODO add token names + console.log(`submitted in in https://solscan.io/tx/${sig}`); } - await new Promise((r) => setTimeout(r, 5000)); + await new Promise((r) => setTimeout(r, SLEEP_MS)); } } catch (error) { console.log(error); @@ -118,7 +125,7 @@ async function preparePullIx( queue: PublicKey, lutOwners: (PublicKey | Oracle)[], pullIxs: TransactionInstruction[], -) { +): Promise { const pullFeed = new PullFeed( sbOnDemandProgram as any, new PublicKey(oracle.oracle.oraclePk), @@ -133,10 +140,10 @@ async function preparePullIx( queue: queue, maxVariance: decodedPullFeed.maxVariance.toNumber(), minResponses: decodedPullFeed.minResponses, - numSignatures: 1, - // TODO: I think these are not required - // minSampleSize: decodedPullFeed.minSampleSize, - // maxStaleness: decodedPullFeed.maxStaleness, + numSignatures: 3, + minSampleSize: decodedPullFeed.minSampleSize, + maxStaleness: decodedPullFeed.maxStaleness, + feedHash: decodedPullFeed.feedHash, }; const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); @@ -157,7 +164,15 @@ async function filterForVarianceThresholdOracles( client: MangoClient, sbOnDemandProgram, crossbarClient: CrossbarClient, -) { +): Promise< + { + oracle: { + oraclePk: PublicKey; + oracleConfig: OracleConfig; + }; + ai: AccountInfo | null; + }[] +> { const varianceThresholdCrossedOracles = new Array<{ oracle: { oraclePk: PublicKey; @@ -187,12 +202,22 @@ async function filterForVarianceThresholdOracles( if ((res.price - simPrice) / res.price > 0.01) { console.log( - `- Variance threshold crossed oracles candidate ${item.oracle.name}`, + `- Variance threshold crossed oracle, candidate ${ + item.oracle.name + } ${simPrice} ${res.price} ${( + ((res.price - simPrice) * 10000) / + res.price + ).toFixed()} bps`, ); varianceThresholdCrossedOracles.push(item); } else { console.log( - `- Variance threshold crossed oracles non candidate ${item.oracle.name}`, + `- Variance threshold crossed oracle, non candidate ${ + item.oracle.name + } ${simPrice} ${res.price} ${( + ((res.price - simPrice) * 10000) / + res.price + ).toFixed()} bps`, ); } } @@ -206,7 +231,15 @@ async function filterForStaleOracles( }[], client: MangoClient, slot: number, -) { +): Promise< + { + oracle: { + oraclePk: PublicKey; + oracleConfig: OracleConfig; + }; + ai: AccountInfo | null; + }[] +> { const staleOracles = new Array<{ oracle: { oraclePk: PublicKey; @@ -222,7 +255,9 @@ async function filterForStaleOracles( ); if (slot > res.lastUpdatedSlot) { - console.log(`- Stale oracle candidate ${item.oracle.name}`); + console.log( + `- Stale oracle, candidate ${item.oracle.name} ${slot} ${res.lastUpdatedSlot}`, + ); if ( slot - res.lastUpdatedSlot > item.oracle.oracleConfig.maxStalenessSlots.toNumber() @@ -230,7 +265,9 @@ async function filterForStaleOracles( staleOracles.push(item); } } else { - console.log(`- Stale oracle non candidate ${item.oracle.name}`); + console.log( + `- Stale oracle, non candidate ${item.oracle.name} ${slot} ${res.lastUpdatedSlot}`, + ); } } return staleOracles; @@ -292,7 +329,7 @@ function extendOraclesManually(cluster: Cluster) { return [ { // https://ondemand.switchboard.xyz/solana/mainnet/user/8SSLjXBEVk9nesbhi9UMCA32uijbVBUqWoKPPQPTekzt/ - oraclePk: new PublicKey('Hrp9Lq2zcSPAtuKCsukrVhawKMWVktfWKPVtLYwveAtu'), + oraclePk: new PublicKey('31VbxqvoswUh6iWwv92mXVdLz7vt2QGV1DZ1tBa64b8w'), oracleConfig: { confFilter: I80F48.fromString('1000'), maxStalenessSlots: new BN(-1), @@ -394,3 +431,23 @@ async function setupSwitchboard(client: MangoClient) { ); return { sbOnDemandProgram, crossbarClient, queue }; } + +async function updateFilteredOraclesAis( + connection: Connection, + filteredOracles: { + oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; + ai: AccountInfo | null; + }[], +): Promise { + const ais = ( + await Promise.all( + chunk( + filteredOracles.map((item) => item.oracle.oraclePk), + 50, + false, + ).map(async (chunk) => await connection.getMultipleAccountsInfo(chunk)), + ) + ).flat(); + + filteredOracles.forEach((fo, idx) => (fo.ai = ais[idx])); +} diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index 178f12d4c..73f308b60 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -98,14 +98,17 @@ async function setupSwitchboard(userProvider: AnchorProvider) { maxRetries: 0, }; + console.log(tier); + const conf = { name: `${TOKEN_SYMBOL}/USD`, // the feed name (max 32 bytes) queue, // the queue of oracles to bind to - maxVariance: 10, // allow 1% variance between submissions and jobs + maxVariance: 1, // allow 1% variance between submissions and jobs minResponses: 2, // minimum number of responses of jobs to allow numSignatures: 3, // number of signatures to fetch per update minSampleSize: 2, // minimum number of responses to sample - maxStaleness: tier!.maxStalenessSlots!, // maximum staleness of responses in seconds to sample + maxStaleness: + tier!.maxStalenessSlots == -1 ? 10000 : tier!.maxStalenessSlots, // maximum staleness of responses in seconds to sample }; console.log('Initializing new data feed'); diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index 5d6d05f35..38abbd9fe 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -130,6 +130,9 @@ export function parseSwitchboardOnDemandOracle( accountInfo.data, ); + // console.log(decodedPullFeed.result); + // console.log(decodedPullFeed.submissions); + if (decodedPullFeed.result == undefined) { const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); const price = new Big(feedValue?.value.toString()).div(1e18); diff --git a/yarn.lock b/yarn.lock index 2b3281e22..d6b644bd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -355,9 +355,9 @@ "@noble/hashes" "1.3.3" "@noble/curves@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" - integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== dependencies: "@noble/hashes" "1.4.0" @@ -602,15 +602,7 @@ bs58 "^4.0.1" superstruct "^0.15.2" -"@solana/spl-token-group@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.3.tgz#e47b0db49cd17c166101cc7650d50a9ee80cba13" - integrity sha512-oEHb/ATHbbzTwP1lNOhLM90lYcUgriMf7KA0L/W/t2OzBplS+5odNDRLccJ7lPstfrZLAAQXbqGGG7E27GXxQQ== - dependencies: - "@solana/codecs" "2.0.0-preview.2" - "@solana/spl-type-length-value" "0.1.0" - -"@solana/spl-token-metadata@^0.1.2", "@solana/spl-token-metadata@^0.1.3": +"@solana/spl-token-metadata@^0.1.2": version "0.1.4" resolved "https://registry.yarnpkg.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.4.tgz#5cdc3b857a8c4a6877df24e24a8648c4132d22ba" integrity sha512-N3gZ8DlW6NWDV28+vCCDJoTqaCZiF/jDUnk3o8GRkAFzHObiR60Bs1gXHBa8zCPdvOwiG6Z3dg5pg7+RW6XNsQ== @@ -649,17 +641,6 @@ "@solana/spl-token-metadata" "^0.1.2" buffer "^6.0.3" -"@solana/spl-token@^0.4.1": - version "0.4.7" - resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.4.7.tgz#5d04969a67707e83d135b3de02216be69e31d86f" - integrity sha512-HvfieHwdGfoz09tl1Ph4uNR48pzl2oXfgMC3NeQ0v3D/Dk6ejTGNPR6xgPbPQ1qJ0ZuyNZOrHudF+GZH3dBybA== - dependencies: - "@solana/buffer-layout" "^4.0.0" - "@solana/buffer-layout-utils" "^0.2.0" - "@solana/spl-token-group" "^0.0.3" - "@solana/spl-token-metadata" "^0.1.3" - buffer "^6.0.3" - "@solana/spl-type-length-value@0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz#b5930cf6c6d8f50c7ff2a70463728a4637a2f26b" @@ -689,9 +670,9 @@ superstruct "^0.14.2" "@solana/web3.js@^1.54.0", "@solana/web3.js@^1.91.1", "@solana/web3.js@^1.93.0": - version "1.93.2" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.93.2.tgz#d928be11dfcd0fc035ea26c1d0c67331b13668ad" - integrity sha512-U8GlrvjfheJTFNavJHb2v/CnpzoqbGKaShLJGf1cELeFUlweUrfYXc9YFX0tw8Icb4ll48vDxt/zEPQOQ29+kw== + version "1.94.0" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.94.0.tgz#f662ce046f59cb294e8304beeb4d549c3ff05d73" + integrity sha512-wMiBebzu5I2fTSz623uj6VXpWFhl0d7qJKqPFK2I4IBLTNUdv+bOeA4H7OBM7Gworv7sOvB3xibRql6l61MeqA== dependencies: "@babel/runtime" "^7.24.7" "@noble/curves" "^1.4.0" @@ -748,13 +729,12 @@ protobufjs "^7.2.6" yaml "^2.2.1" -"@switchboard-xyz/on-demand@^1.1.24": - version "1.1.24" - resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.1.24.tgz#7cf9bdcd1ac30ad4de6ab0286a84fcdbd02ff374" - integrity sha512-IFqwO7j3JsJ9qWPV0oc4hr/4DVavGaBoLWIB132Uf8NLQleIsij8ay36QHeZ+StJurv9NNUbUhzfPrXo6QwYYw== +"@switchboard-xyz/on-demand@^1.1.26": + version "1.1.26" + resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.1.26.tgz#f8c8649d8c79b5dac837177f2d6f3c2693660eef" + integrity sha512-elG2vf0ZOMftv+5Kj+pJ1Mp0yRsdHiGu5VBdYuC+Qorqkpi7aaUbPEjIbiliUX4flxdXbuHYmKkAd/bZoBcpHw== dependencies: "@coral-xyz/anchor" "^0.30.0" - "@solana/spl-token" "^0.4.1" "@solana/web3.js" "^1.91.1" "@solworks/soltoolkit-sdk" "^0.0.23" "@switchboard-xyz/common" "^2.4.2" From 6540ef31c30a46c3003d94e788e74da9002216a8 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Wed, 3 Jul 2024 09:43:29 +0200 Subject: [PATCH 17/40] update Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 92 +++++++++++++++++-------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 71271b5bb..5f8abccb2 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -18,7 +18,7 @@ import { import fs from 'fs'; import chunk from 'lodash/chunk'; import uniqWith from 'lodash/uniqWith'; -import { Program as Anchor30Program } from 'switchboard-anchor'; +import { Program as Anchor30Program, Idl } from 'switchboard-anchor'; import BN from 'bn.js'; import { AnchorProvider, Wallet } from 'switchboard-anchor'; @@ -56,7 +56,11 @@ const SLEEP_MS = Number(process.env.SLEEP_MS) || 5_000; for (let i = 0; i < 10; i++) { const slot = await client.connection.getSlot(); - await updateFilteredOraclesAis(client.connection, filteredOracles); + await updateFilteredOraclesAis( + client.connection, + sbOnDemandProgram, + filteredOracles, + ); const staleOracles = await filterForStaleOracles( filteredOracles, @@ -68,7 +72,6 @@ const SLEEP_MS = Number(process.env.SLEEP_MS) || 5_000; await filterForVarianceThresholdOracles( filteredOracles, client, - sbOnDemandProgram, crossbarClient, ); @@ -138,31 +141,38 @@ async function preparePullIx( const conf = { queue: queue, - maxVariance: decodedPullFeed.maxVariance.toNumber(), - minResponses: decodedPullFeed.minResponses, numSignatures: 3, - minSampleSize: decodedPullFeed.minSampleSize, - maxStaleness: decodedPullFeed.maxStaleness, feedHash: decodedPullFeed.feedHash, }; + // TODO use fetchUpdateMany const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); if (pullIx === undefined) { return; } + // TODO + // > Mitch | Switchboard: + // there can be more oracles that join a queue over time + // all oracles and feeds carry their own LUT as im sure you noticed + // > Mitch | Switchboard: + // the feed ones are easy to predict though + // > Mitch | Switchboard: + // but you dont know which oracles the gateway will select for you so best you can do is pack all oracle accounts into 1lut + const lutOwners_ = [...responses.map((x) => x.oracle), pullFeed.pubkey]; lutOwners.push(...lutOwners_); + pullIxs.push(pullIx!); } async function filterForVarianceThresholdOracles( filteredOracles: { oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; + decodedPullFeed: any; ai: AccountInfo | null; }[], client: MangoClient, - sbOnDemandProgram, crossbarClient: CrossbarClient, ): Promise< { @@ -178,6 +188,7 @@ async function filterForVarianceThresholdOracles( oraclePk: PublicKey; oracleConfig: OracleConfig; }; + decodedPullFeed: any; ai: AccountInfo | null; }>(); for (const item of filteredOracles) { @@ -187,25 +198,20 @@ async function filterForVarianceThresholdOracles( client.connection, ); - const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( - 'pullFeedAccountData', - item.ai!.data, - ); - const crossBarSim = await crossbarClient.simulateFeeds([ - new Buffer(decodedPullFeed.feedHash).toString('hex'), + new Buffer(item.decodedPullFeed.feedHash).toString('hex'), ]); const simPrice = crossBarSim[0].results.reduce((a, b) => a + b, 0) / crossBarSim[0].results.length; - if ((res.price - simPrice) / res.price > 0.01) { + if (Math.abs(res.price - simPrice) / res.price > 0.01) { console.log( `- Variance threshold crossed oracle, candidate ${ item.oracle.name } ${simPrice} ${res.price} ${( - ((res.price - simPrice) * 10000) / + (Math.abs(res.price - simPrice) * 10000) / res.price ).toFixed()} bps`, ); @@ -215,7 +221,7 @@ async function filterForVarianceThresholdOracles( `- Variance threshold crossed oracle, non candidate ${ item.oracle.name } ${simPrice} ${res.price} ${( - ((res.price - simPrice) * 10000) / + (Math.abs(res.price - simPrice) * 10000) / res.price ).toFixed()} bps`, ); @@ -227,6 +233,7 @@ async function filterForVarianceThresholdOracles( async function filterForStaleOracles( filteredOracles: { oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; + decodedPullFeed: any; ai: AccountInfo | null; }[], client: MangoClient, @@ -254,26 +261,37 @@ async function filterForStaleOracles( client.connection, ); - if (slot > res.lastUpdatedSlot) { + if ( + slot > res.lastUpdatedSlot && + slot - res.lastUpdatedSlot > item.decodedPullFeed.maxStaleness + ) { console.log( - `- Stale oracle, candidate ${item.oracle.name} ${slot} ${res.lastUpdatedSlot}`, + `- Stale oracle, candidate ${item.oracle.name} ${slot} ${ + item.decodedPullFeed.maxStaleness + } ${res.lastUpdatedSlot} ${slot - res.lastUpdatedSlot}`, ); - if ( - slot - res.lastUpdatedSlot > - item.oracle.oracleConfig.maxStalenessSlots.toNumber() - ) { - staleOracles.push(item); - } + staleOracles.push(item); } else { console.log( - `- Stale oracle, non candidate ${item.oracle.name} ${slot} ${res.lastUpdatedSlot}`, + `- Stale oracle, non candidate ${item.oracle.name} ${slot} ${ + res.lastUpdatedSlot + } ${res.lastUpdatedSlot} ${slot - res.lastUpdatedSlot}`, ); } } return staleOracles; } -async function prepareCandidateOracles(group: Group, client: MangoClient) { +async function prepareCandidateOracles( + group: Group, + client: MangoClient, +): Promise< + { + oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; + decodedPullFeed: any; + ai: AccountInfo | null; + }[] +> { const oracles = getOraclesForMangoGroup(group); oracles.push(...extendOraclesManually(CLUSTER)); @@ -310,6 +328,7 @@ async function prepareCandidateOracles(group: Group, client: MangoClient) { return { oracle: o, ai: ais[i] }; }) .filter((item) => item.ai?.owner.equals(SB_ON_DEMAND_PID)); + return filteredOracles; } @@ -339,7 +358,12 @@ function extendOraclesManually(cluster: Cluster) { ]; } -async function setupMango() { +async function setupMango(): Promise<{ + group: Group; + client: MangoClient; + connection: Connection; + user: Keypair; +}> { const options = AnchorProvider.defaultOptions(); const connection = new Connection(CLUSTER_URL!, options); const user = Keypair.fromSecretKey( @@ -434,7 +458,9 @@ async function setupSwitchboard(client: MangoClient) { async function updateFilteredOraclesAis( connection: Connection, + sbOnDemandProgram: Anchor30Program, filteredOracles: { + decodedPullFeed: any; oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; ai: AccountInfo | null; }[], @@ -449,5 +475,13 @@ async function updateFilteredOraclesAis( ) ).flat(); - filteredOracles.forEach((fo, idx) => (fo.ai = ais[idx])); + filteredOracles.forEach((fo, idx) => { + fo.ai = ais[idx]; + + const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( + 'pullFeedAccountData', + fo.ai!.data, + ); + fo.decodedPullFeed = decodedPullFeed; + }); } From eeeb336bbc1c1fcb51d739b5316f31b1df39852a Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Wed, 3 Jul 2024 10:34:49 +0200 Subject: [PATCH 18/40] update Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 116 ++++++------------ ts/client/scripts/sb-on-demand-create-feed.ts | 2 +- 2 files changed, 41 insertions(+), 77 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 5f8abccb2..a7cd8b184 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -40,6 +40,16 @@ const SLEEP_MS = Number(process.env.SLEEP_MS) || 5_000; // TODO use mangolana to send txs +interface OracleInterface { + oracle: { + oraclePk: PublicKey; + oracleConfig: OracleConfig; + name: string; + }; + decodedPullFeed: any; + ai: AccountInfo | null; +} + (async function main(): Promise { const { group, client, connection, user } = await setupMango(); @@ -134,15 +144,9 @@ async function preparePullIx( new PublicKey(oracle.oracle.oraclePk), ); - const decodedPullFeed = sbOnDemandProgram.coder.accounts.decode( - 'pullFeedAccountData', - oracle.ai.data, - ); - const conf = { - queue: queue, numSignatures: 3, - feedHash: decodedPullFeed.feedHash, + feed: oracle.oraclePk, }; // TODO use fetchUpdateMany const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); @@ -167,30 +171,11 @@ async function preparePullIx( } async function filterForVarianceThresholdOracles( - filteredOracles: { - oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; - decodedPullFeed: any; - ai: AccountInfo | null; - }[], + filteredOracles: OracleInterface[], client: MangoClient, crossbarClient: CrossbarClient, -): Promise< - { - oracle: { - oraclePk: PublicKey; - oracleConfig: OracleConfig; - }; - ai: AccountInfo | null; - }[] -> { - const varianceThresholdCrossedOracles = new Array<{ - oracle: { - oraclePk: PublicKey; - oracleConfig: OracleConfig; - }; - decodedPullFeed: any; - ai: AccountInfo | null; - }>(); +): Promise { + const varianceThresholdCrossedOracles = new Array(); for (const item of filteredOracles) { const res = await parseSwitchboardOracle( item.oracle.oraclePk, @@ -206,24 +191,16 @@ async function filterForVarianceThresholdOracles( crossBarSim[0].results.reduce((a, b) => a + b, 0) / crossBarSim[0].results.length; - if (Math.abs(res.price - simPrice) / res.price > 0.01) { + const changePct = (Math.abs(res.price - simPrice) * 100) / res.price; + const changeBps = changePct * 100; + if (changePct > item.decodedPullFeed.maxVariance) { console.log( - `- Variance threshold crossed oracle, candidate ${ - item.oracle.name - } ${simPrice} ${res.price} ${( - (Math.abs(res.price - simPrice) * 10000) / - res.price - ).toFixed()} bps`, + `- ${item.oracle.name}, variance threshold, candidate ${simPrice} ${res.price} ${changeBps} bps`, ); varianceThresholdCrossedOracles.push(item); } else { console.log( - `- Variance threshold crossed oracle, non candidate ${ - item.oracle.name - } ${simPrice} ${res.price} ${( - (Math.abs(res.price - simPrice) * 10000) / - res.price - ).toFixed()} bps`, + `- ${item.oracle.name}, variance threshold, non-candidate ${simPrice} ${res.price} ${changeBps} bps`, ); } } @@ -231,11 +208,7 @@ async function filterForVarianceThresholdOracles( } async function filterForStaleOracles( - filteredOracles: { - oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; - decodedPullFeed: any; - ai: AccountInfo | null; - }[], + filteredOracles: OracleInterface[], client: MangoClient, slot: number, ): Promise< @@ -247,13 +220,7 @@ async function filterForStaleOracles( ai: AccountInfo | null; }[] > { - const staleOracles = new Array<{ - oracle: { - oraclePk: PublicKey; - oracleConfig: OracleConfig; - }; - ai: AccountInfo | null; - }>(); + const staleOracles = new Array(); for (const item of filteredOracles) { const res = await parseSwitchboardOracle( item.oracle.oraclePk, @@ -261,21 +228,18 @@ async function filterForStaleOracles( client.connection, ); + const diff = slot - res.lastUpdatedSlot; if ( slot > res.lastUpdatedSlot && slot - res.lastUpdatedSlot > item.decodedPullFeed.maxStaleness ) { console.log( - `- Stale oracle, candidate ${item.oracle.name} ${slot} ${ - item.decodedPullFeed.maxStaleness - } ${res.lastUpdatedSlot} ${slot - res.lastUpdatedSlot}`, + `- ${item.oracle.name}, stale oracle, candidate ${item.decodedPullFeed.maxStaleness} ${slot} ${res.lastUpdatedSlot} ${diff}`, ); staleOracles.push(item); } else { console.log( - `- Stale oracle, non candidate ${item.oracle.name} ${slot} ${ - res.lastUpdatedSlot - } ${res.lastUpdatedSlot} ${slot - res.lastUpdatedSlot}`, + `- ${item.oracle.name}, stale oracle, non-candidate ${item.decodedPullFeed.maxStaleness} ${slot} ${res.lastUpdatedSlot} ${diff}`, ); } } @@ -285,13 +249,7 @@ async function filterForStaleOracles( async function prepareCandidateOracles( group: Group, client: MangoClient, -): Promise< - { - oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; - decodedPullFeed: any; - ai: AccountInfo | null; - }[] -> { +): Promise { const oracles = getOraclesForMangoGroup(group); oracles.push(...extendOraclesManually(CLUSTER)); @@ -325,14 +283,18 @@ async function prepareCandidateOracles( const filteredOracles = oracles .map((o, i) => { - return { oracle: o, ai: ais[i] }; + return { oracle: o, ai: ais[i], decodedPullFeed: undefined }; }) .filter((item) => item.ai?.owner.equals(SB_ON_DEMAND_PID)); return filteredOracles; } -function extendOraclesManually(cluster: Cluster) { +function extendOraclesManually(cluster: Cluster): { + oraclePk: PublicKey; + oracleConfig: { confFilter: I80F48; maxStalenessSlots: BN }; + name: string; +}[] { if (cluster == 'devnet') { return [ { @@ -389,7 +351,9 @@ async function setupMango(): Promise<{ return { group, client, connection, user }; } -function getOraclesForMangoGroup(group: Group) { +function getOraclesForMangoGroup( + group: Group, +): { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }[] { // oracles for tokens const oracles1 = Array.from(group.banksMapByName.values()) .filter( @@ -439,7 +403,11 @@ function getOraclesForMangoGroup(group: Group) { return oracles; } -async function setupSwitchboard(client: MangoClient) { +async function setupSwitchboard(client: MangoClient): Promise<{ + sbOnDemandProgram: Anchor30Program; + crossbarClient: CrossbarClient; + queue: PublicKey; +}> { const idl = await Anchor30Program.fetchIdl( SB_ON_DEMAND_PID, client.program.provider, @@ -459,11 +427,7 @@ async function setupSwitchboard(client: MangoClient) { async function updateFilteredOraclesAis( connection: Connection, sbOnDemandProgram: Anchor30Program, - filteredOracles: { - decodedPullFeed: any; - oracle: { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }; - ai: AccountInfo | null; - }[], + filteredOracles: OracleInterface[], ): Promise { const ais = ( await Promise.all( diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index 73f308b60..aca95ecc3 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -108,7 +108,7 @@ async function setupSwitchboard(userProvider: AnchorProvider) { numSignatures: 3, // number of signatures to fetch per update minSampleSize: 2, // minimum number of responses to sample maxStaleness: - tier!.maxStalenessSlots == -1 ? 10000 : tier!.maxStalenessSlots, // maximum staleness of responses in seconds to sample + tier!.maxStalenessSlots == -1 ? 10000 : tier!.maxStalenessSlots!, // maximum staleness of responses in seconds to sample }; console.log('Initializing new data feed'); From ba70b34524bd1ea190ab7c4d9446c81e086e5943 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Wed, 3 Jul 2024 13:21:31 +0200 Subject: [PATCH 19/40] update Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index a7cd8b184..cf5352dae 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -64,7 +64,7 @@ interface OracleInterface { const filteredOracles = await prepareCandidateOracles(group, client); for (let i = 0; i < 10; i++) { - const slot = await client.connection.getSlot(); + const slot = await client.connection.getSlot('finalized'); await updateFilteredOraclesAis( client.connection, From ccb98fb5b8df269436adb914bd29c44ca5016c07 Mon Sep 17 00:00:00 2001 From: Serge Farny Date: Thu, 4 Jul 2024 21:42:04 +0200 Subject: [PATCH 20/40] Program: bump version --- Cargo.lock | 2 +- mango_v4.json | 2 +- programs/mango-v4/Cargo.toml | 2 +- ts/client/src/mango_v4.ts | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2e8774087..9e7d5c8f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3441,7 +3441,7 @@ dependencies = [ [[package]] name = "mango-v4" -version = "0.24.0" +version = "0.24.1" dependencies = [ "anchor-lang", "anchor-spl", diff --git a/mango_v4.json b/mango_v4.json index 02dc51cc3..5f39a7fbb 100644 --- a/mango_v4.json +++ b/mango_v4.json @@ -1,5 +1,5 @@ { - "version": "0.24.0", + "version": "0.24.1", "name": "mango_v4", "instructions": [ { diff --git a/programs/mango-v4/Cargo.toml b/programs/mango-v4/Cargo.toml index c54c1555e..3729e5524 100644 --- a/programs/mango-v4/Cargo.toml +++ b/programs/mango-v4/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mango-v4" -version = "0.24.0" +version = "0.24.1" description = "Created with Anchor" edition = "2021" diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index 90109a77d..659bc56e9 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -1,5 +1,5 @@ export type MangoV4 = { - "version": "0.24.0", + "version": "0.24.1", "name": "mango_v4", "instructions": [ { @@ -14485,7 +14485,7 @@ export type MangoV4 = { }; export const IDL: MangoV4 = { - "version": "0.24.0", + "version": "0.24.1", "name": "mango_v4", "instructions": [ { From cbd4d12685f0133b9955f4a3df0775133aadbe4e Mon Sep 17 00:00:00 2001 From: Serge Farny Date: Fri, 5 Jul 2024 07:58:15 +0100 Subject: [PATCH 21/40] Update CHANGELOG.md for v0.24.1 --- CHANGELOG.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02dfd0a4d..9cdb19c07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,17 @@ Update this for each program release and mainnet deployment. ## not on mainnet -### v0.24.0, 2024-4- + +### v0.24.1, 2024-7- + +- Support for switchboard on demand oracle (#974) + +- Sip bad oracle in token update index and rate (#975) + + +## mainnet + +### v0.24.0, 2024-4-18 - Allow skipping banks and invalid oracles when computing health (#891) @@ -26,8 +36,6 @@ Update this for each program release and mainnet deployment. Assert that a transaction was emitted and run with a correct view of the current mango state. -## mainnet - ### v0.23.0, 2024-3-8 Deployment: Mar 8, 2024 at 12:10:52 Central European Standard Time, https://explorer.solana.com/tx/6MXGookZoYGMYb7tWrrmgZzVA13HJimHNqwHRVFeqL9YpQD7YasH1pQn4MSQTK1o13ixKTGFxwZsviUzmHzzP9m From eaca2f290667c78b68dbc584525dbcf6ec8ff7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Brzezin=CC=81ski?= Date: Sat, 6 Jul 2024 00:34:33 +0200 Subject: [PATCH 22/40] full feed configuration --- package.json | 6 +- ts/client/scripts/sb-on-demand-create-feed.ts | 740 ++++++++++++++---- yarn.lock | 268 +++++-- 3 files changed, 764 insertions(+), 250 deletions(-) diff --git a/package.json b/package.json index d2b786e3c..4b2359c8c 100644 --- a/package.json +++ b/package.json @@ -63,11 +63,13 @@ "trailingComma": "all" }, "dependencies": { - "@blockworks-foundation/mango-v4-settings": "0.14.15", - "@blockworks-foundation/mangolana": "0.0.14", + "@blockworks-foundation/mango-v4-settings": "0.14.24", + "@blockworks-foundation/mangolana": "0.0.17", "@coral-xyz/anchor": "^0.28.1-beta.2", "@project-serum/serum": "0.13.65", "@pythnetwork/client": "~2.14.0", + "@iarna/toml": "2.2.5", + "@raydium-io/raydium-sdk": "^1.3.1-beta.57", "@solana/spl-token": "0.3.7", "@solana/web3.js": "^1.78.2", "@switchboard-xyz/on-demand": "^1.1.26", diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index aca95ecc3..564479f99 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -1,4 +1,9 @@ -import { LISTING_PRESETS } from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools'; +import { + LISTING_PRESETS, + LISTING_PRESETS_KEY, + tierSwitchboardSettings, + tierToSwitchboardJobSwapValue, +} from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools'; import { Cluster, Commitment, @@ -22,18 +27,34 @@ import { AnchorProvider, Wallet, } from 'switchboard-anchor'; -// basic configuration -const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; -const SWAP_VALUE = '100'; -const TOKEN_MINT = 'MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac'; -const FALLBACK_POOL_NAME: 'orcaPoolAddress' | 'raydiumPoolAddress' = - 'raydiumPoolAddress'; -const FALLBACK_POOL = '34tFULRrRwh4bMcBLPtJaNqqe5pVgGZACi5sR8Xz95KC'; -const TOKEN_SYMBOL = 'MNGO'; -// basic configuration +import { struct, u8, publicKey, u64, option } from '@raydium-io/raydium-sdk'; +import * as toml from '@iarna/toml'; +import { toNative } from '../src/utils'; -const pythUsdOracle = 'Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD'; -const switchboardUsdDaoOracle = 'FwYfsmj5x8YZXtQBNo2Cz8TE7WRCMFqA6UTffK4xQKMH'; +// Configuration +const TIER: LISTING_PRESETS_KEY = 'asset_250'; +const TOKEN_MINT = 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN'; + +// Tier based variables +const swapValue = tierToSwitchboardJobSwapValue[TIER]; +const settingFromLib = tierSwitchboardSettings[TIER]; +const maxVariance = LISTING_PRESETS[TIER].oracleConfFilter * 100; +const minResponses = settingFromLib!.minRequiredOracleResults; +const numSignatures = settingFromLib!.minRequiredOracleResults + 1; +const minSampleSize = settingFromLib!.minRequiredOracleResults; +const maxStaleness = + LISTING_PRESETS[TIER].maxStalenessSlots === -1 + ? 10000 + : LISTING_PRESETS[TIER].maxStalenessSlots; + +// Constants +const JUPITER_PRICE_API_MAINNET = 'https://price.jup.ag/v4/'; +const JUPITER_TOKEN_API_MAINNET = 'https://token.jup.ag/all'; +const WRAPPED_SOL_MINT = 'So11111111111111111111111111111111111111112'; +const PYTH_SOL_ORACLE = 'H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG'; +const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; +const PYTH_USDC_ORACLE = 'Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD'; +const SWITCHBOARD_USDC_ORACLE = 'FwYfsmj5x8YZXtQBNo2Cz8TE7WRCMFqA6UTffK4xQKMH'; const CLUSTER: Cluster = (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; const CLUSTER_URL = @@ -59,6 +80,253 @@ async function setupAnchor() { return { userProvider, connection, user }; } +async function getTokenPrice(mint: string): Promise { + const priceInfo = await ( + await fetch(`${JUPITER_PRICE_API_MAINNET}price?ids=${mint}`) + ).json(); + //Note: if listing asset that don't have price on jupiter remember to edit this 0 to real price + //in case of using 0 openbook market can be wrongly configured ignore if openbook market is existing + const price = priceInfo.data[mint]?.price || 0; + if (!price) { + console.log('Token price not found'); + throw 'Token price not found'; + } + return price; +} + +async function getTokenInfo(mint: string): Promise { + const response = await fetch(JUPITER_TOKEN_API_MAINNET); + const data: Token[] = await response.json(); + const tokenInfo = data.find((x) => x.address === mint); + if (!tokenInfo) { + console.log('Token info not found'); + throw 'Token info not found'; + } + return data.find((x) => x.address === mint); +} + +async function getPool(mint: string): Promise< + | { + pool: string; + poolSource: 'raydium' | 'orca'; + isSolPool: boolean; + isReveredSolPool: boolean; + } + | undefined +> { + const dex = await fetch( + `https://api.dexscreener.com/latest/dex/search?q=${mint}`, + ); + const resp = await dex.json(); + + if (!resp?.pairs?.length) { + return; + } + + const pairs = resp.pairs.filter( + (x) => x.dexId.includes('raydium') || x.dexId.includes('orca'), + ); + + const bestUsdcPool = pairs.find( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (x: any) => x.quoteToken.address === USDC_MINT, + ); + + const bestSolPool = pairs.find( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (x: any) => x.quoteToken.address === WRAPPED_SOL_MINT, + ); + + const bestReversedSolPool = pairs.find( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (x: any) => x.baseToken.address === WRAPPED_SOL_MINT, + ); + + if (bestUsdcPool) { + return { + pool: bestUsdcPool.pairAddress, + poolSource: bestUsdcPool.dexId.includes('raydium') ? 'raydium' : 'orca', + isSolPool: false, + isReveredSolPool: false, + }; + } + + if (bestSolPool) { + return { + pool: bestSolPool.pairAddress, + poolSource: bestSolPool.dexId.includes('raydium') ? 'raydium' : 'orca', + isSolPool: true, + isReveredSolPool: false, + }; + } + + if (bestSolPool) { + return { + pool: bestReversedSolPool.pairAddress, + poolSource: bestReversedSolPool.dexId.includes('raydium') + ? 'raydium' + : 'orca', + isSolPool: true, + isReveredSolPool: true, + }; + } + + console.log('No orca or raydium pool found'); + throw 'No orca or raydium pool found'; +} + +const getLstStakePool = async ( + connection: Connection, + mint: string, +): Promise => { + try { + let poolAddress = ''; + let addresses: string[] = []; + try { + const tomlFile = await fetch( + `https://raw.githubusercontent.com/${'igneous-labs'}/${'sanctum-lst-list'}/master/sanctum-lst-list.toml`, + ); + + const tomlText = await tomlFile.text(); + const tomlData = toml.parse(tomlText) as unknown as { + sanctum_lst_list: { pool: { pool: string } }[]; + }; + addresses = [ + ...tomlData.sanctum_lst_list + .map((x) => tryGetPubKey(x.pool.pool)?.toBase58()) + .filter((x) => x), + ] as string[]; + } catch (e) { + console.log(e); + } + + //remove duplicates + const possibleStakePoolsAddresses = [...new Set(addresses)].map( + (x) => new PublicKey(x), + ); + + const accounts = await connection.getMultipleAccountsInfo( + possibleStakePoolsAddresses, + ); + for (const idx in accounts) { + try { + const acc = accounts[idx]; + const stakeAddressPk = possibleStakePoolsAddresses[idx]; + if (acc?.data) { + const decoded = StakePoolLayout.decode(acc?.data); + if (decoded.poolMint.toBase58() === mint && stakeAddressPk) { + poolAddress = stakeAddressPk?.toBase58(); + break; + } + } + // eslint-disable-next-line no-empty + } catch (e) {} + } + + return poolAddress; + } catch (e) { + console.log(e); + return ''; + } +}; + +const LSTExactIn = ( + inMint: string, + nativeInAmount: string, + stakePoolAddress: string, +): string => { + const template = `tasks: + - conditionalTask: + attempt: + - httpTask: + url: https://api.sanctum.so/v1/swap/quote?input=${inMint}&outputLstMint=So11111111111111111111111111111111111111112&amount=${nativeInAmount}&mode=ExactIn + - jsonParseTask: + path: $.outAmount + - divideTask: + scalar: ${nativeInAmount} + onFailure: + - splStakePoolTask: + pubkey: ${stakePoolAddress} + - cacheTask: + cacheItems: + - variableName: poolTokenSupply + job: + tasks: + - jsonParseTask: + path: $.uiPoolTokenSupply + aggregationMethod: NONE + - variableName: totalStakeLamports + job: + tasks: + - jsonParseTask: + path: $.uiTotalLamports + aggregationMethod: NONE + - valueTask: + big: \${totalStakeLamports} + - divideTask: + big: \${poolTokenSupply} + - multiplyTask: + job: + tasks: + - oracleTask: + pythAddress: H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG + pythAllowedConfidenceInterval: 10`; + return template; +}; + +const LSTExactOut = ( + inMint: string, + nativeOutSolAmount: string, + stakePoolAddress: string, +): string => { + const template = `tasks: + - conditionalTask: + attempt: + - cacheTask: + cacheItems: + - variableName: QTY + job: + tasks: + - httpTask: + url: https://api.sanctum.so/v1/swap/quote?input=${inMint}&outputLstMint=So11111111111111111111111111111111111111112&amount=${nativeOutSolAmount}&mode=ExactOut + - jsonParseTask: + path: $.inAmount + - httpTask: + url: https://api.sanctum.so/v1/swap/quote?input=${inMint}&outputLstMint=So11111111111111111111111111111111111111112&amount=\${QTY}&mode=ExactIn + - jsonParseTask: + path: $.outAmount + - divideTask: + big: \${QTY} + onFailure: + - splStakePoolTask: + pubkey: ${stakePoolAddress} + - cacheTask: + cacheItems: + - variableName: poolTokenSupply + job: + tasks: + - jsonParseTask: + path: $.uiPoolTokenSupply + aggregationMethod: NONE + - variableName: totalStakeLamports + job: + tasks: + - jsonParseTask: + path: $.uiTotalLamports + aggregationMethod: NONE + - valueTask: + big: \${totalStakeLamports} + - divideTask: + big: \${poolTokenSupply} + - multiplyTask: + job: + tasks: + - oracleTask: + pythAddress: H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG + pythAllowedConfidenceInterval: 10`; + return template; +}; + async function setupSwitchboard(userProvider: AnchorProvider) { const idl = await Anchor30Program.fetchIdl(SB_ON_DEMAND_PID, userProvider); const sbOnDemandProgram = new Anchor30Program(idl!, userProvider); @@ -74,15 +342,26 @@ async function setupSwitchboard(userProvider: AnchorProvider) { } (async function main(): Promise { - const tier = Object.values(LISTING_PRESETS).find( - (x) => x.preset_name === 'C', - ); - const { userProvider, connection, user } = await setupAnchor(); + const [ + { sbOnDemandProgram, crossbarClient, queue }, + poolInfo, + price, + tokeninfo, + lstPool, + ] = await Promise.all([ + setupSwitchboard(userProvider), + getPool(TOKEN_MINT), + getTokenPrice(TOKEN_MINT), + getTokenInfo(TOKEN_MINT), + getLstStakePool(connection, TOKEN_MINT), + ]); - const { sbOnDemandProgram, crossbarClient, queue } = await setupSwitchboard( - userProvider, - ); + const FALLBACK_POOL_NAME: 'orcaPoolAddress' | 'raydiumPoolAddress' = `${ + poolInfo!.poolSource + }PoolAddress`; + const FALLBACK_POOL = poolInfo!.pool; + const TOKEN_SYMBOL = tokeninfo!.symbol.toUpperCase(); const queueAccount = new Queue(sbOnDemandProgram, queue); try { @@ -92,185 +371,256 @@ async function setupSwitchboard(userProvider: AnchorProvider) { return; } + let onFailureTaskDesc: { [key: string]: any }[]; + if (!poolInfo?.isReveredSolPool) { + onFailureTaskDesc = [ + { + lpExchangeRateTask: { + [FALLBACK_POOL_NAME]: FALLBACK_POOL, + }, + }, + ]; + if (poolInfo?.isSolPool) { + onFailureTaskDesc.push({ + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + pythAddress: PYTH_SOL_ORACLE, + pythAllowedConfidenceInterval: 10, + }, + }, + ], + }, + }, + }); + } + } else { + onFailureTaskDesc = [ + { + valueTask: { + big: 1, + }, + }, + { + divideTask: { + job: { + tasks: [ + { + lpExchangeRateTask: { + [FALLBACK_POOL_NAME]: FALLBACK_POOL, + }, + }, + ], + }, + }, + }, + ]; + if (poolInfo.isSolPool) { + onFailureTaskDesc.push({ + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + pythAddress: PYTH_SOL_ORACLE, + pythAllowedConfidenceInterval: 10, + }, + }, + ], + }, + }, + }); + } + } + const txOpts = { commitment: 'finalized' as Commitment, skipPreflight: true, maxRetries: 0, }; - console.log(tier); - const conf = { name: `${TOKEN_SYMBOL}/USD`, // the feed name (max 32 bytes) queue, // the queue of oracles to bind to - maxVariance: 1, // allow 1% variance between submissions and jobs - minResponses: 2, // minimum number of responses of jobs to allow - numSignatures: 3, // number of signatures to fetch per update - minSampleSize: 2, // minimum number of responses to sample - maxStaleness: - tier!.maxStalenessSlots == -1 ? 10000 : tier!.maxStalenessSlots!, // maximum staleness of responses in seconds to sample + maxVariance: maxVariance!, // allow 1% variance between submissions and jobs + minResponses: minResponses!, // minimum number of responses of jobs to allow + numSignatures: numSignatures!, // number of signatures to fetch per update + minSampleSize: minSampleSize!, // minimum number of responses to sample + maxStaleness: maxStaleness!, // maximum staleness of responses in seconds to sample }; console.log('Initializing new data feed'); // Generate the feed keypair const [pullFeed, feedKp] = PullFeed.generate(sbOnDemandProgram); const jobs = [ - OracleJob.fromObject({ - tasks: [ - { - conditionalTask: { - attempt: [ - { - valueTask: { - big: SWAP_VALUE, - }, - }, - { - divideTask: { - job: { - tasks: [ - { - jupiterSwapTask: { - inTokenAddress: USDC_MINT, - outTokenAddress: TOKEN_MINT, - baseAmountString: SWAP_VALUE, - }, - }, - ], + lstPool + ? OracleJob.fromYaml( + LSTExactIn( + TOKEN_MINT, + toNative( + Math.ceil(Number(swapValue) / price), + tokeninfo!.decimals, + ).toString(), + lstPool, + ), + ) + : OracleJob.fromObject({ + tasks: [ + { + conditionalTask: { + attempt: [ + { + valueTask: { + big: swapValue, + }, }, - }, - }, - ], - onFailure: [ - { - lpExchangeRateTask: { - [FALLBACK_POOL_NAME]: FALLBACK_POOL, - }, - }, - ], - }, - }, - { - conditionalTask: { - attempt: [ - { - multiplyTask: { - job: { - tasks: [ - { - oracleTask: { - pythAddress: pythUsdOracle, - pythAllowedConfidenceInterval: 10, - }, - }, - ], - }, - }, - }, - ], - onFailure: [ - { - multiplyTask: { - job: { - tasks: [ - { - oracleTask: { - switchboardAddress: switchboardUsdDaoOracle, - }, - }, - ], - }, - }, - }, - ], - }, - }, - ], - }), - OracleJob.fromObject({ - tasks: [ - { - conditionalTask: { - attempt: [ - { - cacheTask: { - cacheItems: [ - { - variableName: 'QTY', + { + divideTask: { job: { tasks: [ { jupiterSwapTask: { inTokenAddress: USDC_MINT, outTokenAddress: TOKEN_MINT, - baseAmountString: SWAP_VALUE, + baseAmountString: swapValue, }, }, ], }, }, - ], - }, - }, - { - jupiterSwapTask: { - inTokenAddress: TOKEN_MINT, - outTokenAddress: USDC_MINT, - baseAmountString: '${QTY}', - }, - }, - { - divideTask: { - big: '${QTY}', - }, - }, - ], - onFailure: [ - { - lpExchangeRateTask: { - [FALLBACK_POOL_NAME]: FALLBACK_POOL, - }, - }, - ], - }, - }, - { - conditionalTask: { - attempt: [ - { - multiplyTask: { - job: { - tasks: [ - { - oracleTask: { - pythAddress: pythUsdOracle, - pythAllowedConfidenceInterval: 10, - }, - }, - ], }, - }, + ], + onFailure: onFailureTaskDesc, }, - ], - onFailure: [ - { - multiplyTask: { - job: { - tasks: [ - { - oracleTask: { - switchboardAddress: switchboardUsdDaoOracle, - }, + }, + { + conditionalTask: { + attempt: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + pythAddress: PYTH_USDC_ORACLE, + pythAllowedConfidenceInterval: 10, + }, + }, + ], }, - ], + }, }, - }, + ], + onFailure: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + switchboardAddress: SWITCHBOARD_USDC_ORACLE, + }, + }, + ], + }, + }, + }, + ], }, - ], - }, - }, - ], - }), + }, + ], + }), + lstPool + ? OracleJob.fromYaml( + LSTExactOut( + TOKEN_MINT, + toNative( + Math.ceil(Number(swapValue) / price), + tokeninfo!.decimals, + ).toString(), + lstPool, + ), + ) + : OracleJob.fromObject({ + tasks: [ + { + conditionalTask: { + attempt: [ + { + cacheTask: { + cacheItems: [ + { + variableName: 'QTY', + job: { + tasks: [ + { + jupiterSwapTask: { + inTokenAddress: USDC_MINT, + outTokenAddress: TOKEN_MINT, + baseAmountString: swapValue, + }, + }, + ], + }, + }, + ], + }, + }, + { + jupiterSwapTask: { + inTokenAddress: TOKEN_MINT, + outTokenAddress: USDC_MINT, + baseAmountString: '${QTY}', + }, + }, + { + divideTask: { + big: '${QTY}', + }, + }, + ], + onFailure: onFailureTaskDesc, + }, + }, + { + conditionalTask: { + attempt: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + pythAddress: PYTH_USDC_ORACLE, + pythAllowedConfidenceInterval: 10, + }, + }, + ], + }, + }, + }, + ], + onFailure: [ + { + multiplyTask: { + job: { + tasks: [ + { + oracleTask: { + switchboardAddress: SWITCHBOARD_USDC_ORACLE, + }, + }, + ], + }, + }, + }, + ], + }, + }, + ], + }), ]; const decodedFeedHash = await crossbarClient .store(queue.toBase58(), jobs) @@ -290,3 +640,61 @@ async function setupSwitchboard(userProvider: AnchorProvider) { const sig = await connection.sendTransaction(tx, txOpts); console.log(`Feed ${feedKp.publicKey} initialized: ${sig}`); })(); + +export type Token = { + address: string; + chainId: number; + decimals: number; + name: string; + symbol: string; + logoURI: string; + extensions: { + coingeckoId?: string; + }; + tags: string[]; +}; + +const feeFields = [u64('denominator'), u64('numerator')]; +const StakePoolLayout = struct([ + u8('accountType'), + publicKey('manager'), + publicKey('staker'), + publicKey('stakeDepositAuthority'), + u8('stakeWithdrawBumpSeed'), + publicKey('validatorList'), + publicKey('reserveStake'), + publicKey('poolMint'), + publicKey('managerFeeAccount'), + publicKey('tokenProgramId'), + u64('totalLamports'), + u64('poolTokenSupply'), + u64('lastUpdateEpoch'), + struct( + [u64('unixTimestamp'), u64('epoch'), publicKey('custodian')], + 'lockup', + ), + struct(feeFields, 'epochFee'), + option(struct(feeFields), 'nextEpochFee'), + option(publicKey(), 'preferredDepositValidatorVoteAddress'), + option(publicKey(), 'preferredWithdrawValidatorVoteAddress'), + struct(feeFields, 'stakeDepositFee'), + struct(feeFields, 'stakeWithdrawalFee'), + option(struct(feeFields), 'nextStakeWithdrawalFee'), + u8('stakeReferralFee'), + option(publicKey(), 'solDepositAuthority'), + struct(feeFields, 'solDepositFee'), + u8('solReferralFee'), + option(publicKey(), 'solWithdrawAuthority'), + struct(feeFields, 'solWithdrawalFee'), + option(struct(feeFields), 'nextSolWithdrawalFee'), + u64('lastEpochPoolTokenSupply'), + u64('lastEpochTotalLamports'), +]); + +const tryGetPubKey = (pubkey: string | string[]) => { + try { + return new PublicKey(pubkey); + } catch (e) { + return null; + } +}; diff --git a/yarn.lock b/yarn.lock index d6b644bd1..17a21a7f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -37,23 +37,23 @@ dependencies: regenerator-runtime "^0.14.0" -"@blockworks-foundation/mango-v4-settings@0.14.15": - version "0.14.15" - resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.14.15.tgz#0ac04f2cffbd27a4129bc2086ec1418e29393880" - integrity sha512-GBo43KCosdaohbtS3Rtz8e2zsLsiN3JqTfLKVtStRYO3f2tQLzeo/D2Khz07psw2egq6TCNZJH7+v32iGrPq0w== +"@blockworks-foundation/mango-v4-settings@0.14.24": + version "0.14.24" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4-settings/-/mango-v4-settings-0.14.24.tgz#646b0802fb6222654e247bea7966106af9b7a970" + integrity sha512-X3mY2x6XSZTySfB65b5DWuE7v/tffMlFGXQsgv+Zl+cgHdJn77vqdXvQFlR+544xsTjK+kWpWiHTHiSWRzG/4Q== dependencies: bn.js "^5.2.1" eslint-config-prettier "^9.0.0" -"@blockworks-foundation/mangolana@0.0.14": - version "0.0.14" - resolved "https://registry.yarnpkg.com/@blockworks-foundation/mangolana/-/mangolana-0.0.14.tgz#f2a0e164f2cbe6e0a0db4fc10267e81ef5d2f7ec" - integrity sha512-KuA2+GdeKoHCBmx2HZnVb8IPomUP1w0ZiwQ1F10SLIypYfrylvPa+HSK2ak/+nzZCb8erS9Oub45UPV7cOh5ng== +"@blockworks-foundation/mangolana@0.0.17": + version "0.0.17" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/mangolana/-/mangolana-0.0.17.tgz#9f9a227c61faa3fba8c99a645b1897c46d8edea7" + integrity sha512-k4YXV5DjzF3hUJS9NYJCtkPVYgLV/EuKv/XDLEmnWX66V3YopST7aHmdfzj1tb8QJDuE3t+aRC66WXOeGNTUpA== dependencies: - "@solana/web3.js" "^1.88.0" + "@solana/web3.js" "^1.91.6" bs58 "^5.0.0" isomorphic-ws "^5.0.0" - node-fetch "2.6.11" + node-fetch "3.3.2" ws "^8.16.0" "@colors/colors@1.5.0": @@ -275,6 +275,18 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" @@ -329,6 +341,11 @@ resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@iarna/toml@2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" + integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== + "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" @@ -512,6 +529,22 @@ "@coral-xyz/anchor" "^0.26.0" buffer "^6.0.1" +"@raydium-io/raydium-sdk@^1.3.1-beta.57": + version "1.3.1-beta.57" + resolved "https://registry.yarnpkg.com/@raydium-io/raydium-sdk/-/raydium-sdk-1.3.1-beta.57.tgz#ca498a2b0c54454cc444e9a55d7ac690f9ba094a" + integrity sha512-oHp9/N4CUEUmxxupaYr+gbrgGiZci9QJ/UX146G2jd0tSkcXu046EV1SE2HSJRnQfMFiJUoxwZi7qzENWH6dDQ== + dependencies: + "@solana/buffer-layout" "^4.0.1" + "@solana/spl-token" "^0.3.9" + axios "^1.6.2" + big.js "^6.2.1" + bn.js "^5.2.1" + decimal.js "^10.4.3" + decimal.js-light "^2.5.1" + fecha "^4.2.3" + lodash "^4.17.21" + toformat "^2.0.0" + "@solana/buffer-layout-utils@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" @@ -631,7 +664,7 @@ buffer-layout "^1.2.0" dotenv "10.0.0" -"@solana/spl-token@^0.3.4": +"@solana/spl-token@^0.3.4", "@solana/spl-token@^0.3.9": version "0.3.11" resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== @@ -648,7 +681,7 @@ dependencies: buffer "^6.0.3" -"@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.78.2", "@solana/web3.js@^1.88.0": +"@solana/web3.js@^1.17.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.78.2": version "1.88.0" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.88.0.tgz#24e1482f63ac54914430b4ce5ab36eaf433ecdb8" integrity sha512-E4BdfB0HZpb66OPFhIzPApNE2tG75Mc6XKIoeymUkx/IV+USSYuxDX29sjgE/KGNYxggrOf4YuYnRMI6UiPL8w== @@ -669,7 +702,7 @@ rpc-websockets "^7.5.1" superstruct "^0.14.2" -"@solana/web3.js@^1.54.0", "@solana/web3.js@^1.91.1", "@solana/web3.js@^1.93.0": +"@solana/web3.js@^1.54.0", "@solana/web3.js@^1.91.1", "@solana/web3.js@^1.91.6", "@solana/web3.js@^1.93.0": version "1.94.0" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.94.0.tgz#f662ce046f59cb294e8304beeb4d549c3ff05d73" integrity sha512-wMiBebzu5I2fTSz623uj6VXpWFhl0d7qJKqPFK2I4IBLTNUdv+bOeA4H7OBM7Gworv7sOvB3xibRql6l61MeqA== @@ -820,9 +853,9 @@ "@types/node" "*" "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/json5@^0.0.29": version "0.0.29" @@ -876,6 +909,11 @@ dependencies: undici-types "~5.26.4" +"@types/semver@^7.3.12": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + "@types/uuid@^8.3.4": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -896,83 +934,87 @@ "@types/node" "*" "@typescript-eslint/eslint-plugin@^5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.32.0.tgz" - integrity sha512-CHLuz5Uz7bHP2WgVlvoZGhf0BvFakBJKAD/43Ty0emn4wXWv5k01ND0C0fHcl/Im8Td2y/7h44E9pca9qAu2ew== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== dependencies: - "@typescript-eslint/scope-manager" "5.32.0" - "@typescript-eslint/type-utils" "5.32.0" - "@typescript-eslint/utils" "5.32.0" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" - functional-red-black-tree "^1.0.1" + graphemer "^1.4.0" ignore "^5.2.0" - regexpp "^3.2.0" + natural-compare-lite "^1.4.0" semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/parser@^5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.32.0.tgz" - integrity sha512-IxRtsehdGV9GFQ35IGm5oKKR2OGcazUoiNBxhRV160iF9FoyuXxjY+rIqs1gfnd+4eL98OjeGnMpE7RF/NBb3A== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== dependencies: - "@typescript-eslint/scope-manager" "5.32.0" - "@typescript-eslint/types" "5.32.0" - "@typescript-eslint/typescript-estree" "5.32.0" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.32.0.tgz" - integrity sha512-KyAE+tUON0D7tNz92p1uetRqVJiiAkeluvwvZOqBmW9z2XApmk5WSMV9FrzOroAcVxJZB3GfUwVKr98Dr/OjOg== +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== dependencies: - "@typescript-eslint/types" "5.32.0" - "@typescript-eslint/visitor-keys" "5.32.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/type-utils@5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.32.0.tgz" - integrity sha512-0gSsIhFDduBz3QcHJIp3qRCvVYbqzHg8D6bHFsDMrm0rURYDj+skBK2zmYebdCp+4nrd9VWd13egvhYFJj/wZg== +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== dependencies: - "@typescript-eslint/utils" "5.32.0" + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.32.0.tgz" - integrity sha512-EBUKs68DOcT/EjGfzywp+f8wG9Zw6gj6BjWu7KV/IYllqKJFPlZlLSYw/PTvVyiRw50t6wVbgv4p9uE2h6sZrQ== +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/typescript-estree@5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.32.0.tgz" - integrity sha512-ZVAUkvPk3ITGtCLU5J4atCw9RTxK+SRc6hXqLtllC2sGSeMFWN+YwbiJR9CFrSFJ3w4SJfcWtDwNb/DmUIHdhg== +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== dependencies: - "@typescript-eslint/types" "5.32.0" - "@typescript-eslint/visitor-keys" "5.32.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.32.0.tgz" - integrity sha512-W7lYIAI5Zlc5K082dGR27Fczjb3Q57ECcXefKU/f0ajM5ToM0P+N9NmJWip8GmGu/g6QISNT+K6KYB+iSHjXCQ== +"@typescript-eslint/utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.32.0" - "@typescript-eslint/types" "5.32.0" - "@typescript-eslint/typescript-estree" "5.32.0" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" + semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.32.0": - version "5.32.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.32.0.tgz" - integrity sha512-S54xOHZgfThiZ38/ZGTgB2rqx51CMJ5MCfVT2IplK4Q7hgzGfe0nLzLCcenDnc/cSjP568hdeKfeDcBgqNHD/g== +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: - "@typescript-eslint/types" "5.32.0" + "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" "@ungap/promise-all-settled@1.1.2": @@ -1125,7 +1167,7 @@ axios@^1.1.3, axios@^1.4.0: form-data "^4.0.0" proxy-from-env "^1.1.0" -axios@^1.2.0, axios@^1.7.2: +axios@^1.2.0, axios@^1.6.2, axios@^1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== @@ -1473,6 +1515,11 @@ crypto-hash@^1.3.0: resolved "https://registry.npmjs.org/crypto-hash/-/crypto-hash-1.3.0.tgz" integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -1492,6 +1539,11 @@ decamelize@^4.0.0: resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decimal.js-light@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== + decimal.js@^10.4.0, decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" @@ -1672,13 +1724,6 @@ eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" @@ -1849,6 +1894,19 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fecha@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" @@ -1920,6 +1978,13 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" @@ -2012,6 +2077,11 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + growl@1.10.5: version "1.10.5" resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" @@ -2508,6 +2578,11 @@ nanoid@3.3.1: resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" @@ -2533,12 +2608,10 @@ node-cache@^5.1.2: dependencies: clone "2.x" -node-fetch@2.6.11, node-fetch@^2.6.1: - version "2.6.11" - resolved "https://registry.yarnpkg.com/@blockworks-foundation/node-fetch/-/node-fetch-2.6.11.tgz#fb536ef0e6a960e7b7993f3c1d3b3bba9bdfbc56" - integrity sha512-HeDTxpIypSR4qCoqgUXGr8YL4OG1z7BbV4VhQ9iQs+pt2wV3MtqO+sQk2vXK3WDKu5C6BsbGmWE22BmIrcuOOw== - dependencies: - whatwg-url "^5.0.0" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== node-fetch@2.6.7: version "2.6.7" @@ -2547,6 +2620,22 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +node-fetch@^2.6.1: + version "2.6.11" + resolved "https://registry.yarnpkg.com/@blockworks-foundation/node-fetch/-/node-fetch-2.6.11.tgz#fb536ef0e6a960e7b7993f3c1d3b3bba9bdfbc56" + integrity sha512-HeDTxpIypSR4qCoqgUXGr8YL4OG1z7BbV4VhQ9iQs+pt2wV3MtqO+sQk2vXK3WDKu5C6BsbGmWE22BmIrcuOOw== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -2735,7 +2824,7 @@ regenerator-runtime@^0.14.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== -regexpp@^3.1.0, regexpp@^3.2.0: +regexpp@^3.1.0: version "3.2.0" resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -2831,13 +2920,18 @@ secp256k1@5.0.0: node-addon-api "^5.0.0" node-gyp-build "^4.2.0" -semver@^7.2.1, semver@^7.3.7: +semver@^7.2.1: version "7.3.7" resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" +semver@^7.3.7: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" @@ -3020,6 +3114,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toformat@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" + integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== + toml@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz" @@ -3094,7 +3193,7 @@ tsconfig-paths@^3.5.0: tslib@^1.8.1: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.3: @@ -3109,7 +3208,7 @@ tslib@^2.4.0: tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -3206,6 +3305,11 @@ vscode-textmate@5.2.0: resolved "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz" integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" From 1bb9271b04839a901c89d11444f89f2a54ccf13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Brzezin=CC=81ski?= Date: Sat, 6 Jul 2024 01:07:50 +0200 Subject: [PATCH 23/40] fix --- ts/client/scripts/sb-on-demand-create-feed.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-create-feed.ts b/ts/client/scripts/sb-on-demand-create-feed.ts index 564479f99..379f91674 100644 --- a/ts/client/scripts/sb-on-demand-create-feed.ts +++ b/ts/client/scripts/sb-on-demand-create-feed.ts @@ -358,9 +358,9 @@ async function setupSwitchboard(userProvider: AnchorProvider) { ]); const FALLBACK_POOL_NAME: 'orcaPoolAddress' | 'raydiumPoolAddress' = `${ - poolInfo!.poolSource + poolInfo?.poolSource || 'raydium' }PoolAddress`; - const FALLBACK_POOL = poolInfo!.pool; + const FALLBACK_POOL = poolInfo?.pool; const TOKEN_SYMBOL = tokeninfo!.symbol.toUpperCase(); const queueAccount = new Queue(sbOnDemandProgram, queue); From 21aa7676d6a0f25c7ab202a92f1b3056f23bb3cc Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 09:50:11 +0200 Subject: [PATCH 24/40] add new oracles Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 48 ++++++++++--------------- ts/client/src/client.ts | 2 +- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index cf5352dae..857dd1cca 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -20,14 +20,13 @@ import chunk from 'lodash/chunk'; import uniqWith from 'lodash/uniqWith'; import { Program as Anchor30Program, Idl } from 'switchboard-anchor'; -import BN from 'bn.js'; import { AnchorProvider, Wallet } from 'switchboard-anchor'; import { OracleConfig } from '../src/accounts/bank'; import { Group } from '../src/accounts/group'; import { parseSwitchboardOracle } from '../src/accounts/oracle'; import { MangoClient } from '../src/client'; import { MANGO_V4_ID, MANGO_V4_MAIN_GROUP } from '../src/constants'; -import { I80F48, ZERO_I80F48 } from '../src/numbers/I80F48'; +import { ZERO_I80F48 } from '../src/numbers/I80F48'; const CLUSTER: Cluster = (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; @@ -43,7 +42,6 @@ const SLEEP_MS = Number(process.env.SLEEP_MS) || 5_000; interface OracleInterface { oracle: { oraclePk: PublicKey; - oracleConfig: OracleConfig; name: string; }; decodedPullFeed: any; @@ -85,7 +83,7 @@ interface OracleInterface { crossbarClient, ); - const oraclesToCrank = uniqWith( + const oraclesToCrank: OracleInterface[] = uniqWith( [...staleOracles, ...varianceThresholdCrossedOracles], function (item) { return item.oracle.oraclePk.toString(); @@ -134,7 +132,7 @@ interface OracleInterface { async function preparePullIx( sbOnDemandProgram, - oracle: any, + oracle: OracleInterface, queue: PublicKey, lutOwners: (PublicKey | Oracle)[], pullIxs: TransactionInstruction[], @@ -146,7 +144,7 @@ async function preparePullIx( const conf = { numSignatures: 3, - feed: oracle.oraclePk, + feed: oracle.oracle.oraclePk, }; // TODO use fetchUpdateMany const [pullIx, responses, success] = await pullFeed.fetchUpdateIx(conf); @@ -211,15 +209,7 @@ async function filterForStaleOracles( filteredOracles: OracleInterface[], client: MangoClient, slot: number, -): Promise< - { - oracle: { - oraclePk: PublicKey; - oracleConfig: OracleConfig; - }; - ai: AccountInfo | null; - }[] -> { +): Promise { const staleOracles = new Array(); for (const item of filteredOracles) { const res = await parseSwitchboardOracle( @@ -292,32 +282,30 @@ async function prepareCandidateOracles( function extendOraclesManually(cluster: Cluster): { oraclePk: PublicKey; - oracleConfig: { confFilter: I80F48; maxStalenessSlots: BN }; name: string; }[] { if (cluster == 'devnet') { return [ { oraclePk: new PublicKey('EtbG8PSDCyCSmDH8RE4Nf2qTV9d6P6zShzHY2XWvjFJf'), - oracleConfig: { - confFilter: I80F48.fromString('0.1'), - maxStalenessSlots: new BN(5), - }, name: 'BTC/USD', }, ]; } return [ - { - // https://ondemand.switchboard.xyz/solana/mainnet/user/8SSLjXBEVk9nesbhi9UMCA32uijbVBUqWoKPPQPTekzt/ - oraclePk: new PublicKey('31VbxqvoswUh6iWwv92mXVdLz7vt2QGV1DZ1tBa64b8w'), - oracleConfig: { - confFilter: I80F48.fromString('1000'), - maxStalenessSlots: new BN(-1), - }, - name: 'MNGO/USD', - }, - ]; + ['JUP', '2F9M59yYc28WMrAymNWceaBEk8ZmDAjUAKULp8seAJF3'], + ['RAY', 'AJkAFiXdbMonys8rTXZBrRnuUiLcDFdkyoPuvrVKXhex'], + ['ORCA', 'HYrGEJsApRqAc9Z1kL7yHCWtU2Gpa6hmxsGt7GybCpCo'], + ['GUAC', 'Ai2GsLRioGKwVgWX8dtbLF5rJJEZX17SteGEDqrpzBv3'], + ['INF', 'AZcoqpWhMJUaKEDUfKsfzCr3Y96gSQwv43KSQ6KpeyQ1'], + ['JLP', '65J9bVEMhNbtbsNgArNV1K4krzcsomjho4bgR51sZXoj'], + ['DIGITSOL', '2A7aqNLy26ZBSMWP2Ekxv926hj16tCA47W1sHWVqaLii'], + ].map((item) => { + return { + oraclePk: new PublicKey(item[0]), + name: item[1], + }; + }); } async function setupMango(): Promise<{ diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index a3737d7b1..9bed25486 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -4594,7 +4594,7 @@ export class MangoClient { if (buyTokenPriceImpact <= 0 || sellTokenPriceImpact <= 0) { throw new Error( - `Error compitong slippage/premium for token conditional swap!`, + `Error computing slippage/premium for token conditional swap!`, ); } From 1342f0f07885df8950dcab977a692e6327b8d3c7 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 09:58:28 +0200 Subject: [PATCH 25/40] fix indexing Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 857dd1cca..cd8c61de0 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -302,8 +302,8 @@ function extendOraclesManually(cluster: Cluster): { ['DIGITSOL', '2A7aqNLy26ZBSMWP2Ekxv926hj16tCA47W1sHWVqaLii'], ].map((item) => { return { - oraclePk: new PublicKey(item[0]), - name: item[1], + oraclePk: new PublicKey(item[1]), + name: item[0], }; }); } From f2e9f2cf8692dff701033e0d7c09808a050ce993 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 10:01:30 +0200 Subject: [PATCH 26/40] remove missing Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index cd8c61de0..5f61d30ac 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -293,13 +293,12 @@ function extendOraclesManually(cluster: Cluster): { ]; } return [ - ['JUP', '2F9M59yYc28WMrAymNWceaBEk8ZmDAjUAKULp8seAJF3'], - ['RAY', 'AJkAFiXdbMonys8rTXZBrRnuUiLcDFdkyoPuvrVKXhex'], - ['ORCA', 'HYrGEJsApRqAc9Z1kL7yHCWtU2Gpa6hmxsGt7GybCpCo'], - ['GUAC', 'Ai2GsLRioGKwVgWX8dtbLF5rJJEZX17SteGEDqrpzBv3'], - ['INF', 'AZcoqpWhMJUaKEDUfKsfzCr3Y96gSQwv43KSQ6KpeyQ1'], - ['JLP', '65J9bVEMhNbtbsNgArNV1K4krzcsomjho4bgR51sZXoj'], ['DIGITSOL', '2A7aqNLy26ZBSMWP2Ekxv926hj16tCA47W1sHWVqaLii'], + ['JLP', '65J9bVEMhNbtbsNgArNV1K4krzcsomjho4bgR51sZXoj'], + ['INF', 'AZcoqpWhMJUaKEDUfKsfzCr3Y96gSQwv43KSQ6KpeyQ1'], + ['GUAC', 'Ai2GsLRioGKwVgWX8dtbLF5rJJEZX17SteGEDqrpzBv3'], + ['RAY', 'AJkAFiXdbMonys8rTXZBrRnuUiLcDFdkyoPuvrVKXhex'], + ['JUP', '2F9M59yYc28WMrAymNWceaBEk8ZmDAjUAKULp8seAJF3'], ].map((item) => { return { oraclePk: new PublicKey(item[1]), From 663126328be5ab82818a7048a767b1dd0f90e0d6 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 10:05:50 +0200 Subject: [PATCH 27/40] update timer Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 5f61d30ac..0dcd65b22 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -35,7 +35,7 @@ const CLUSTER_URL = const USER_KEYPAIR = process.env.USER_KEYPAIR_OVERRIDE || process.env.MB_PAYER_KEYPAIR; const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); -const SLEEP_MS = Number(process.env.SLEEP_MS) || 5_000; +const SLEEP_MS = Number(process.env.SLEEP_MS) || 100_000; // 100s // TODO use mangolana to send txs From 1248a120de61e030ec4b57913ee21fb2bead71b4 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 10:10:25 +0200 Subject: [PATCH 28/40] update sender Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 0dcd65b22..c77d25067 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -1,7 +1,6 @@ import { AccountInfo, Cluster, - Commitment, Connection, Keypair, PublicKey, @@ -27,6 +26,7 @@ import { parseSwitchboardOracle } from '../src/accounts/oracle'; import { MangoClient } from '../src/client'; import { MANGO_V4_ID, MANGO_V4_MAIN_GROUP } from '../src/constants'; import { ZERO_I80F48 } from '../src/numbers/I80F48'; +import { sendTransaction } from '../src/utils/rpc'; const CLUSTER: Cluster = (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; @@ -49,7 +49,7 @@ interface OracleInterface { } (async function main(): Promise { - const { group, client, connection, user } = await setupMango(); + const { group, client, connection, user, userProvider } = await setupMango(); const { sbOnDemandProgram, crossbarClient, queue } = await setupSwitchboard( client, @@ -112,14 +112,14 @@ interface OracleInterface { lookupTables: await loadLookupTables(lutOwners), }); - const txOpts = { - commitment: 'processed' as Commitment, - skipPreflight: true, - maxRetries: 0, - }; - - const sig = await client.connection.sendTransaction(tx, txOpts); - console.log(`submitted in in https://solscan.io/tx/${sig}`); + const ret = sendTransaction( + userProvider, + [...c], + await loadLookupTables(lutOwners), + ); + console.log( + `submitted in in https://solscan.io/tx/${(await ret).signature}`, + ); } await new Promise((r) => setTimeout(r, SLEEP_MS)); @@ -335,7 +335,7 @@ async function setupMango(): Promise<{ const group = await client.getGroup(new PublicKey(GROUP)); await group.reloadAll(client); - return { group, client, connection, user }; + return { group, client, connection, user, userProvider }; } function getOraclesForMangoGroup( From b7ab52634a8233dd7509a319893b1f84d45d485d Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 10:17:09 +0200 Subject: [PATCH 29/40] fix prio fee Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index c77d25067..b8233faf5 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -7,7 +7,6 @@ import { TransactionInstruction, } from '@solana/web3.js'; import { - asV0Tx, CrossbarClient, loadLookupTables, Oracle, @@ -103,19 +102,11 @@ interface OracleInterface { } for (const c of chunk(pullIxs, 5, false)) { - const tx = await asV0Tx({ - connection, - ixs: [...c], - signers: [user], - computeUnitPrice: 200_000, - computeUnitLimitMultiple: 1.3, - lookupTables: await loadLookupTables(lutOwners), - }); - const ret = sendTransaction( userProvider, [...c], await loadLookupTables(lutOwners), + { prioritizationFee: 100 }, ); console.log( `submitted in in https://solscan.io/tx/${(await ret).signature}`, From fef1a97528a6a59d3251a2190d5ee7680482764d Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 10:36:36 +0200 Subject: [PATCH 30/40] more general fixes Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 65 ++++++++++++++----------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index b8233faf5..941999548 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -19,7 +19,6 @@ import uniqWith from 'lodash/uniqWith'; import { Program as Anchor30Program, Idl } from 'switchboard-anchor'; import { AnchorProvider, Wallet } from 'switchboard-anchor'; -import { OracleConfig } from '../src/accounts/bank'; import { Group } from '../src/accounts/group'; import { parseSwitchboardOracle } from '../src/accounts/oracle'; import { MangoClient } from '../src/client'; @@ -75,17 +74,24 @@ interface OracleInterface { slot, ); + const crossBarSims = await Promise.all( + filteredOracles.map( + async (fo) => + await crossbarClient.simulateFeeds([ + new Buffer(fo.decodedPullFeed.feedHash).toString('hex'), + ]), + ), + ); const varianceThresholdCrossedOracles = await filterForVarianceThresholdOracles( filteredOracles, client, - crossbarClient, + crossBarSims, ); - const oraclesToCrank: OracleInterface[] = uniqWith( [...staleOracles, ...varianceThresholdCrossedOracles], - function (item) { - return item.oracle.oraclePk.toString(); + function (a, b) { + return a.oracle.oraclePk.equals(b.oracle.oraclePk); }, ); @@ -101,17 +107,19 @@ interface OracleInterface { ); } - for (const c of chunk(pullIxs, 5, false)) { - const ret = sendTransaction( - userProvider, - [...c], - await loadLookupTables(lutOwners), - { prioritizationFee: 100 }, - ); - console.log( - `submitted in in https://solscan.io/tx/${(await ret).signature}`, - ); - } + await Promise.all( + chunk(pullIxs, 2, false).map(async (ixsChunk) => { + const ret = sendTransaction( + userProvider, + [...ixsChunk], + await loadLookupTables(lutOwners), + { prioritizationFee: 100 }, + ); + console.log( + `submitted in in https://solscan.io/tx/${(await ret).signature}`, + ); + }), + ); await new Promise((r) => setTimeout(r, SLEEP_MS)); } @@ -162,19 +170,17 @@ async function preparePullIx( async function filterForVarianceThresholdOracles( filteredOracles: OracleInterface[], client: MangoClient, - crossbarClient: CrossbarClient, + crossBarSims, ): Promise { const varianceThresholdCrossedOracles = new Array(); - for (const item of filteredOracles) { + for (const [index, item] of filteredOracles.entries()) { const res = await parseSwitchboardOracle( item.oracle.oraclePk, item.ai!, client.connection, ); - const crossBarSim = await crossbarClient.simulateFeeds([ - new Buffer(item.decodedPullFeed.feedHash).toString('hex'), - ]); + const crossBarSim = crossBarSims[index]; const simPrice = crossBarSim[0].results.reduce((a, b) => a + b, 0) / @@ -184,12 +190,12 @@ async function filterForVarianceThresholdOracles( const changeBps = changePct * 100; if (changePct > item.decodedPullFeed.maxVariance) { console.log( - `- ${item.oracle.name}, variance threshold, candidate ${simPrice} ${res.price} ${changeBps} bps`, + `- ${item.oracle.name}, variance threshold, candidate, simPrice ${simPrice}, res.price ${res.price}, change ${changeBps} bps`, ); varianceThresholdCrossedOracles.push(item); } else { console.log( - `- ${item.oracle.name}, variance threshold, non-candidate ${simPrice} ${res.price} ${changeBps} bps`, + `- ${item.oracle.name}, variance threshold, non-candidate, simPrice ${simPrice}, res.price ${res.price}, change ${changeBps} bps`, ); } } @@ -215,12 +221,12 @@ async function filterForStaleOracles( slot - res.lastUpdatedSlot > item.decodedPullFeed.maxStaleness ) { console.log( - `- ${item.oracle.name}, stale oracle, candidate ${item.decodedPullFeed.maxStaleness} ${slot} ${res.lastUpdatedSlot} ${diff}`, + `- ${item.oracle.name}, stale oracle, candidate, maxStaleness ${item.decodedPullFeed.maxStaleness}, slot ${slot}, res.lastUpdatedSlot ${res.lastUpdatedSlot}, diff ${diff}`, ); staleOracles.push(item); } else { console.log( - `- ${item.oracle.name}, stale oracle, non-candidate ${item.decodedPullFeed.maxStaleness} ${slot} ${res.lastUpdatedSlot} ${diff}`, + `- ${item.oracle.name}, stale oracle, non-candidate, maxStaleness ${item.decodedPullFeed.maxStaleness}, slot ${slot}, res.lastUpdatedSlot ${res.lastUpdatedSlot}, diff ${diff}`, ); } } @@ -303,6 +309,7 @@ async function setupMango(): Promise<{ client: MangoClient; connection: Connection; user: Keypair; + userProvider: AnchorProvider; }> { const options = AnchorProvider.defaultOptions(); const connection = new Connection(CLUSTER_URL!, options); @@ -331,7 +338,7 @@ async function setupMango(): Promise<{ function getOraclesForMangoGroup( group: Group, -): { oraclePk: PublicKey; oracleConfig: OracleConfig; name: string }[] { +): { oraclePk: PublicKey; name: string }[] { // oracles for tokens const oracles1 = Array.from(group.banksMapByName.values()) .filter( @@ -345,7 +352,7 @@ function getOraclesForMangoGroup( .map((b) => { return { oraclePk: b[0].oracle, - oracleConfig: b[0].oracleConfig, + name: b[0].name, }; }); @@ -354,7 +361,7 @@ function getOraclesForMangoGroup( const oracles2 = Array.from(group.perpMarketsMapByName.values()).map((pM) => { return { oraclePk: pM.oracle, - oracleConfig: pM.oracleConfig, + name: pM.name, }; }); @@ -372,7 +379,7 @@ function getOraclesForMangoGroup( .map((b) => { return { oraclePk: b[0].oracle, - oracleConfig: b[0].oracleConfig, + name: b[0].name, }; }) From 0a7ac6441371a0434433f9e95e082f28d4b01418 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 10:41:20 +0200 Subject: [PATCH 31/40] swallow errors Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 941999548..d228cd6f8 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -109,15 +109,21 @@ interface OracleInterface { await Promise.all( chunk(pullIxs, 2, false).map(async (ixsChunk) => { - const ret = sendTransaction( - userProvider, - [...ixsChunk], - await loadLookupTables(lutOwners), - { prioritizationFee: 100 }, - ); - console.log( - `submitted in in https://solscan.io/tx/${(await ret).signature}`, - ); + try { + const ret = sendTransaction( + userProvider, + [...ixsChunk], + await loadLookupTables(lutOwners), + { prioritizationFee: 100 }, + ); + console.log( + `submitted in in https://solscan.io/tx/${ + (await ret).signature + }`, + ); + } catch (error) { + console.log(`Error in sending tx, ${error}`); + } }), ); From 23d6f93de85a7c7207caca8e36327337d278afb9 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 10:46:59 +0200 Subject: [PATCH 32/40] small logging improvement Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index d228cd6f8..06ff8eb0b 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -95,6 +95,12 @@ interface OracleInterface { }, ); + console.log( + `- round candidates ${oraclesToCrank + .map((o) => o.oracle.name) + .join(', ')}`, + ); + const pullIxs: TransactionInstruction[] = []; const lutOwners: (PublicKey | Oracle)[] = []; for (const oracle of oraclesToCrank) { @@ -117,9 +123,7 @@ interface OracleInterface { { prioritizationFee: 100 }, ); console.log( - `submitted in in https://solscan.io/tx/${ - (await ret).signature - }`, + `submitted in https://solscan.io/tx/${(await ret).signature}`, ); } catch (error) { console.log(`Error in sending tx, ${error}`); From 036569d5d710599acd1463401ad58ae7a69dbe6a Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 11:02:03 +0200 Subject: [PATCH 33/40] improve parsing Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 1 + ts/client/src/accounts/oracle.ts | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 06ff8eb0b..f0b7f01eb 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -189,6 +189,7 @@ async function filterForVarianceThresholdOracles( item.ai!, client.connection, ); + // console.log(`${item.oracle.name} ${JSON.stringify(res)}`); const crossBarSim = crossBarSims[index]; diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index 38abbd9fe..5437c950a 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -130,21 +130,22 @@ export function parseSwitchboardOnDemandOracle( accountInfo.data, ); + // useful for development // console.log(decodedPullFeed.result); // console.log(decodedPullFeed.submissions); - if (decodedPullFeed.result == undefined) { - const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); - const price = new Big(feedValue?.value.toString()).div(1e18); - const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! - const stdDeviation = 0; // TODO the 0 - return { price, lastUpdatedSlot, uiDeviation: stdDeviation }; - } - - const price = new Big(decodedPullFeed.result.value.toString()).div(1e18); - const lastUpdatedSlot = decodedPullFeed.result.slot.toNumber(); - const stdDeviation = decodedPullFeed.result.stdDev.toNumber(); + const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); + console.log(feedValue); + const price = new Big(feedValue?.value.toString()).div(1e18); + const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! + const stdDeviation = 0; // TODO the 0 return { price, lastUpdatedSlot, uiDeviation: stdDeviation }; + + // old block, we prefer above block since we want raw data, .result is often empty + // const price = new Big(decodedPullFeed.result.value.toString()).div(1e18); + // const lastUpdatedSlot = decodedPullFeed.result.slot.toNumber(); + // const stdDeviation = decodedPullFeed.result.stdDev.toNumber(); + // return { price, lastUpdatedSlot, uiDeviation: stdDeviation }; } catch (e) { console.log( `Unable to parse Switchboard On-Demand Oracle V2: ${oracle}`, From 53fd2fa709bc41ecffbb99890ff7fcc9e2ad8bf2 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 11:02:32 +0200 Subject: [PATCH 34/40] remove stray log Signed-off-by: microwavedcola1 --- ts/client/src/accounts/oracle.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index 5437c950a..594a76616 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -135,7 +135,6 @@ export function parseSwitchboardOnDemandOracle( // console.log(decodedPullFeed.submissions); const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); - console.log(feedValue); const price = new Big(feedValue?.value.toString()).div(1e18); const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! const stdDeviation = 0; // TODO the 0 From b02ec278ee4446323bd479784c8c6bfd6fa6b1ea Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 11:07:12 +0200 Subject: [PATCH 35/40] update default Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index f0b7f01eb..055340e4d 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -33,7 +33,7 @@ const CLUSTER_URL = const USER_KEYPAIR = process.env.USER_KEYPAIR_OVERRIDE || process.env.MB_PAYER_KEYPAIR; const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); -const SLEEP_MS = Number(process.env.SLEEP_MS) || 100_000; // 100s +const SLEEP_MS = Number(process.env.SLEEP_MS) || 50_000; // 100s // TODO use mangolana to send txs From c16b2933ce1c5f2eafead5bc31fe15bb3671fd2d Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 11:24:36 +0200 Subject: [PATCH 36/40] use mangolana Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 51 ++++++++++++++++--------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 055340e4d..96b6f179b 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -8,7 +8,6 @@ import { } from '@solana/web3.js'; import { CrossbarClient, - loadLookupTables, Oracle, PullFeed, SB_ON_DEMAND_PID, @@ -18,13 +17,15 @@ import chunk from 'lodash/chunk'; import uniqWith from 'lodash/uniqWith'; import { Program as Anchor30Program, Idl } from 'switchboard-anchor'; +import { SequenceType } from '@blockworks-foundation/mangolana/lib/globalTypes'; +import { sendSignAndConfirmTransactions } from '@blockworks-foundation/mangolana/lib/transactions'; import { AnchorProvider, Wallet } from 'switchboard-anchor'; import { Group } from '../src/accounts/group'; import { parseSwitchboardOracle } from '../src/accounts/oracle'; import { MangoClient } from '../src/client'; import { MANGO_V4_ID, MANGO_V4_MAIN_GROUP } from '../src/constants'; import { ZERO_I80F48 } from '../src/numbers/I80F48'; -import { sendTransaction } from '../src/utils/rpc'; +import { createComputeBudgetIx } from '../src/utils/rpc'; const CLUSTER: Cluster = (process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta'; @@ -113,23 +114,35 @@ interface OracleInterface { ); } - await Promise.all( - chunk(pullIxs, 2, false).map(async (ixsChunk) => { - try { - const ret = sendTransaction( - userProvider, - [...ixsChunk], - await loadLookupTables(lutOwners), - { prioritizationFee: 100 }, - ); - console.log( - `submitted in https://solscan.io/tx/${(await ret).signature}`, - ); - } catch (error) { - console.log(`Error in sending tx, ${error}`); - } - }), - ); + const ixsChunks = chunk(pullIxs, 2, false); + try { + // use mangolana + await sendSignAndConfirmTransactions({ + connection, + wallet: new Wallet(user), + transactionInstructions: ixsChunks.map((txChunk) => ({ + instructionsSet: [ + { + signers: [], + transactionInstruction: createComputeBudgetIx(80000), + }, + ...txChunk.map((tx) => ({ + signers: [], + transactionInstruction: tx, + })), + ], + sequenceType: SequenceType.Sequential, + })), + config: { + maxRetries: 5, + autoRetry: true, + maxTxesInBatch: 20, + logFlowInfo: false, + }, + }); + } catch (error) { + console.log(`Error in sending tx, ${error}`); + } await new Promise((r) => setTimeout(r, SLEEP_MS)); } From a9cd25140de47bf5c66d2512d8969b4a3066cff7 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 11:26:41 +0200 Subject: [PATCH 37/40] small logging improvement Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 96b6f179b..32bf4178e 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -97,9 +97,11 @@ interface OracleInterface { ); console.log( - `- round candidates ${oraclesToCrank + `- round candidates stale ${staleOracles .map((o) => o.oracle.name) - .join(', ')}`, + .join(', ')}, variance ${varianceThresholdCrossedOracles + .map((o) => o.oracle.name) + .join(', ')}}`, ); const pullIxs: TransactionInstruction[] = []; From 37a2c06df78e15179303a61f088f8ad9eec79a37 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 11:26:58 +0200 Subject: [PATCH 38/40] small logging improvement Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 32bf4178e..3bf71cc10 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -101,7 +101,7 @@ interface OracleInterface { .map((o) => o.oracle.name) .join(', ')}, variance ${varianceThresholdCrossedOracles .map((o) => o.oracle.name) - .join(', ')}}`, + .join(', ')}`, ); const pullIxs: TransactionInstruction[] = []; From e2180553445daaf8f693879a004ba7a2ef273641 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 11:28:22 +0200 Subject: [PATCH 39/40] small logging improvement Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 3bf71cc10..8b9788b4c 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -97,9 +97,9 @@ interface OracleInterface { ); console.log( - `- round candidates stale ${staleOracles + `- round candidates | Stale: ${staleOracles .map((o) => o.oracle.name) - .join(', ')}, variance ${varianceThresholdCrossedOracles + .join(', ')} | Variance: ${varianceThresholdCrossedOracles .map((o) => o.oracle.name) .join(', ')}`, ); From 33fc12b78e6ab808f04314654d6619c4e821fe42 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sun, 7 Jul 2024 22:35:07 +0200 Subject: [PATCH 40/40] update to crank and decoding Signed-off-by: microwavedcola1 --- ts/client/scripts/sb-on-demand-crank.ts | 38 ++++++++++++++++++++----- ts/client/src/accounts/oracle.ts | 21 ++++++++++---- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/ts/client/scripts/sb-on-demand-crank.ts b/ts/client/scripts/sb-on-demand-crank.ts index 8b9788b4c..312a6e82b 100644 --- a/ts/client/scripts/sb-on-demand-crank.ts +++ b/ts/client/scripts/sb-on-demand-crank.ts @@ -36,6 +36,9 @@ const USER_KEYPAIR = const GROUP = process.env.GROUP_OVERRIDE || MANGO_V4_MAIN_GROUP.toBase58(); const SLEEP_MS = Number(process.env.SLEEP_MS) || 50_000; // 100s +console.log(`Starting with ${SLEEP_MS}`); +console.log(`${CLUSTER_URL}`); + // TODO use mangolana to send txs interface OracleInterface { @@ -104,6 +107,23 @@ interface OracleInterface { .join(', ')}`, ); + // todo use chunk + // todo use luts + + // const [pullIxs, luts] = await PullFeed.fetchUpdateManyIx( + // sbOnDemandProgram, + // { + // feeds: oraclesToCrank.map((o) => new PublicKey(o.oracle.oraclePk)), + // numSignatures: 3, + // }, + // ); + + // console.log( + // oraclesToCrank + // .map((o) => new PublicKey(o.oracle.oraclePk)) + // .toString(), + // ); + const pullIxs: TransactionInstruction[] = []; const lutOwners: (PublicKey | Oracle)[] = []; for (const oracle of oraclesToCrank) { @@ -143,7 +163,7 @@ interface OracleInterface { }, }); } catch (error) { - console.log(`Error in sending tx, ${error}`); + console.log(`Error in sending tx, ${JSON.stringify(error)}`); } await new Promise((r) => setTimeout(r, SLEEP_MS)); @@ -167,7 +187,7 @@ async function preparePullIx( ); const conf = { - numSignatures: 3, + numSignatures: 2, feed: oracle.oracle.oraclePk, }; // TODO use fetchUpdateMany @@ -214,14 +234,18 @@ async function filterForVarianceThresholdOracles( const changePct = (Math.abs(res.price - simPrice) * 100) / res.price; const changeBps = changePct * 100; - if (changePct > item.decodedPullFeed.maxVariance) { + if (changePct > item.decodedPullFeed.maxVariance / 1000000000) { console.log( - `- ${item.oracle.name}, variance threshold, candidate, simPrice ${simPrice}, res.price ${res.price}, change ${changeBps} bps`, + `- ${item.oracle.name}, candidate, ${ + item.decodedPullFeed.maxVariance / 1000000000 + }, ${simPrice}, ${res.price}, ${changePct}`, ); varianceThresholdCrossedOracles.push(item); } else { console.log( - `- ${item.oracle.name}, variance threshold, non-candidate, simPrice ${simPrice}, res.price ${res.price}, change ${changeBps} bps`, + `- ${item.oracle.name}, non-candidate, ${ + item.decodedPullFeed.maxVariance / 1000000000 + }, ${simPrice}, ${res.price}, ${changePct}`, ); } } @@ -247,12 +271,12 @@ async function filterForStaleOracles( slot - res.lastUpdatedSlot > item.decodedPullFeed.maxStaleness ) { console.log( - `- ${item.oracle.name}, stale oracle, candidate, maxStaleness ${item.decodedPullFeed.maxStaleness}, slot ${slot}, res.lastUpdatedSlot ${res.lastUpdatedSlot}, diff ${diff}`, + `- ${item.oracle.name}, candidate, ${item.decodedPullFeed.maxStaleness}, ${slot}, ${res.lastUpdatedSlot}, ${diff}`, ); staleOracles.push(item); } else { console.log( - `- ${item.oracle.name}, stale oracle, non-candidate, maxStaleness ${item.decodedPullFeed.maxStaleness}, slot ${slot}, res.lastUpdatedSlot ${res.lastUpdatedSlot}, diff ${diff}`, + `- ${item.oracle.name}, non-candidate, ${item.decodedPullFeed.maxStaleness}, ${slot}, ${res.lastUpdatedSlot}, ${diff}`, ); } } diff --git a/ts/client/src/accounts/oracle.ts b/ts/client/src/accounts/oracle.ts index 594a76616..48b2e3cbc 100644 --- a/ts/client/src/accounts/oracle.ts +++ b/ts/client/src/accounts/oracle.ts @@ -1,7 +1,7 @@ import { AnchorProvider, Wallet } from '@coral-xyz/anchor'; import { Magic as PythMagic } from '@pythnetwork/client'; import { AccountInfo, Connection, Keypair, PublicKey } from '@solana/web3.js'; -import { SB_ON_DEMAND_PID, toFeedValue } from '@switchboard-xyz/on-demand'; +import { SB_ON_DEMAND_PID } from '@switchboard-xyz/on-demand'; import SwitchboardProgram from '@switchboard-xyz/sbv2-lite'; import Big from 'big.js'; import BN from 'bn.js'; @@ -131,12 +131,23 @@ export function parseSwitchboardOnDemandOracle( ); // useful for development - // console.log(decodedPullFeed.result); + // console.log(decodedPullFeed); // console.log(decodedPullFeed.submissions); - const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); - const price = new Big(feedValue?.value.toString()).div(1e18); - const lastUpdatedSlot = feedValue!.slot!.toNumber(); // TODO the ! + // Use custom code instead of toFeedValue from sb on demand sdk + // Custom code which has uses min sample size + // const feedValue = toFeedValue(decodedPullFeed.submissions, new BN(0)); + let values = decodedPullFeed.submissions.slice( + 0, + decodedPullFeed.minSampleSize, + ); + if (values.length === 0) { + return { price: 0, lastUpdatedSlot: 0, uiDeviation: 0 }; + } + values = values.sort((x, y) => (x.value.lt(y.value) ? -1 : 1)); + const feedValue = values[Math.floor(values.length / 2)]; + const price = new Big(feedValue.value.toString()).div(1e18); + const lastUpdatedSlot = feedValue.slot.toNumber(); const stdDeviation = 0; // TODO the 0 return { price, lastUpdatedSlot, uiDeviation: stdDeviation };