From 2d9d2a2462d907c04b4457fe267adf72f3153c41 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 8 Jul 2023 14:48:04 +0700 Subject: [PATCH 001/173] yarn.lock file update --- yarn.lock | 1117 ++++++++++++----------------------------------------- 1 file changed, 239 insertions(+), 878 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9bded9e..ab3ddb1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,15 +2,20 @@ # yarn lockfile v1 +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== "@dabh/diagnostics@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31" - integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== dependencies: colorspace "1.1.x" enabled "2.0.x" @@ -31,21 +36,6 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@ethersproject/abi@5.5.0", "@ethersproject/abi@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" - integrity sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w== - dependencies: - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" @@ -61,19 +51,6 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/abstract-provider@5.5.1", "@ethersproject/abstract-provider@^5.5.0": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" - integrity sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/networks" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/web" "^5.5.0" - "@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" @@ -87,17 +64,6 @@ "@ethersproject/transactions" "^5.7.0" "@ethersproject/web" "^5.7.0" -"@ethersproject/abstract-signer@5.5.0", "@ethersproject/abstract-signer@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" - integrity sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" @@ -109,17 +75,6 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.5.0", "@ethersproject/address@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" - integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - "@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" @@ -131,13 +86,6 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/rlp" "^5.7.0" -"@ethersproject/base64@5.5.0", "@ethersproject/base64@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" - integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" @@ -145,14 +93,6 @@ dependencies: "@ethersproject/bytes" "^5.7.0" -"@ethersproject/basex@5.5.0", "@ethersproject/basex@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.5.0.tgz#e40a53ae6d6b09ab4d977bd037010d4bed21b4d3" - integrity sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" @@ -161,15 +101,6 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" - integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - bn.js "^4.11.9" - "@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" @@ -179,13 +110,6 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.5.0", "@ethersproject/bytes@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" - integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== - dependencies: - "@ethersproject/logger" "^5.5.0" - "@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" @@ -193,13 +117,6 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/constants@5.5.0", "@ethersproject/constants@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" - integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" @@ -207,22 +124,6 @@ dependencies: "@ethersproject/bignumber" "^5.7.0" -"@ethersproject/contracts@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.5.0.tgz#b735260d4bd61283a670a82d5275e2a38892c197" - integrity sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg== - dependencies: - "@ethersproject/abi" "^5.5.0" - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/contracts@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" @@ -248,20 +149,6 @@ ethers "^5.7.0" scrypt-js "3.0.1" -"@ethersproject/hash@5.5.0", "@ethersproject/hash@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" - integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== - dependencies: - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" @@ -277,24 +164,6 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/hdnode@5.5.0", "@ethersproject/hdnode@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.5.0.tgz#4a04e28f41c546f7c978528ea1575206a200ddf6" - integrity sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q== - dependencies: - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/basex" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/pbkdf2" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/signing-key" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/wordlists" "^5.5.0" - "@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" @@ -313,25 +182,6 @@ "@ethersproject/transactions" "^5.7.0" "@ethersproject/wordlists" "^5.7.0" -"@ethersproject/json-wallets@5.5.0", "@ethersproject/json-wallets@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz#dd522d4297e15bccc8e1427d247ec8376b60e325" - integrity sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ== - dependencies: - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/hdnode" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/pbkdf2" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/random" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - "@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" @@ -351,14 +201,6 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" - integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== - dependencies: - "@ethersproject/bytes" "^5.5.0" - js-sha3 "0.8.0" - "@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" @@ -367,23 +209,11 @@ "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.5.0", "@ethersproject/logger@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" - integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== - "@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== -"@ethersproject/networks@5.5.2", "@ethersproject/networks@^5.5.0": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.2.tgz#784c8b1283cd2a931114ab428dae1bd00c07630b" - integrity sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ== - dependencies: - "@ethersproject/logger" "^5.5.0" - "@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": version "5.7.1" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" @@ -391,14 +221,6 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/pbkdf2@5.5.0", "@ethersproject/pbkdf2@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz#e25032cdf02f31505d47afbf9c3e000d95c4a050" - integrity sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" @@ -407,13 +229,6 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/sha2" "^5.7.0" -"@ethersproject/properties@5.5.0", "@ethersproject/properties@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" - integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== - dependencies: - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" @@ -421,58 +236,7 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.5.2", "@ethersproject/providers@^5.5.0": - version "5.5.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.2.tgz#131ccf52dc17afd0ab69ed444b8c0e3a27297d99" - integrity sha512-hkbx7x/MKcRjyrO4StKXCzCpWer6s97xnm34xkfPiarhtEUVAN4TBBpamM+z66WcTt7H5B53YwbRj1n7i8pZoQ== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/basex" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/networks" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/random" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/web" "^5.5.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/providers@5.7.1": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.1.tgz#b0799b616d5579cd1067a8ebf1fc1ec74c1e122c" - integrity sha512-vZveG/DLyo+wk4Ga1yx6jSEHrLPgmTt+dFv0dv8URpVCRf0jVhalps1jq/emN/oXnMRsC7cQgAF32DcXLL7BPQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/providers@5.7.2": +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.5.0": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -498,14 +262,6 @@ bech32 "1.1.4" ws "7.4.6" -"@ethersproject/random@5.5.1", "@ethersproject/random@^5.5.0": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.1.tgz#7cdf38ea93dc0b1ed1d8e480ccdaf3535c555415" - integrity sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" @@ -514,14 +270,6 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/rlp@5.5.0", "@ethersproject/rlp@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" - integrity sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" @@ -530,15 +278,6 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/sha2@5.5.0", "@ethersproject/sha2@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" - integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - hash.js "1.1.7" - "@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" @@ -548,18 +287,6 @@ "@ethersproject/logger" "^5.7.0" hash.js "1.1.7" -"@ethersproject/signing-key@5.5.0", "@ethersproject/signing-key@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" - integrity sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - bn.js "^4.11.9" - elliptic "6.5.4" - hash.js "1.1.7" - "@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" @@ -572,18 +299,6 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.5.0.tgz#2662eb3e5da471b85a20531e420054278362f93f" - integrity sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/solidity@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" @@ -596,15 +311,6 @@ "@ethersproject/sha2" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/strings@5.5.0", "@ethersproject/strings@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" - integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" @@ -614,21 +320,6 @@ "@ethersproject/constants" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/transactions@5.5.0", "@ethersproject/transactions@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" - integrity sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA== - dependencies: - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - "@ethersproject/signing-key" "^5.5.0" - "@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" @@ -644,15 +335,6 @@ "@ethersproject/rlp" "^5.7.0" "@ethersproject/signing-key" "^5.7.0" -"@ethersproject/units@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.5.0.tgz#104d02db5b5dc42cc672cc4587bafb87a95ee45e" - integrity sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/units@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" @@ -662,27 +344,6 @@ "@ethersproject/constants" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/wallet@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.5.0.tgz#322a10527a440ece593980dca6182f17d54eae75" - integrity sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/hdnode" "^5.5.0" - "@ethersproject/json-wallets" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/random" "^5.5.0" - "@ethersproject/signing-key" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/wordlists" "^5.5.0" - "@ethersproject/wallet@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" @@ -704,17 +365,6 @@ "@ethersproject/transactions" "^5.7.0" "@ethersproject/wordlists" "^5.7.0" -"@ethersproject/web@5.5.1", "@ethersproject/web@^5.5.0": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316" - integrity sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg== - dependencies: - "@ethersproject/base64" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": version "5.7.1" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" @@ -726,17 +376,6 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/wordlists@5.5.0", "@ethersproject/wordlists@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.5.0.tgz#aac74963aa43e643638e5172353d931b347d584f" - integrity sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" @@ -749,9 +388,9 @@ "@ethersproject/strings" "^5.7.0" "@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -806,9 +445,9 @@ integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== "@types/mocha@10.0.1": version "10.0.1" @@ -828,9 +467,9 @@ integrity sha512-leyIuBk/rMIp9114FlPRkc/cQG+/JzCz1Afx3BD+CwK2ep3ZRxoC843V1rqnE2pC/jRRjANWhuVBEn4clCwlug== "@types/node@*": - version "18.11.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.0.tgz#f38c7139247a1d619f6cc6f27b072606af7c289d" - integrity sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w== + version "20.4.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.1.tgz#a6033a8718653c50ac4962977e14d0f984d9527d" + integrity sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg== "@types/node@16.11.13": version "16.11.13" @@ -838,9 +477,14 @@ integrity sha512-eUXZzHLHoZqj1frtUetNkUetYoJ6X55UmrVnFD4DMhVeAmwLjniZhtBmsRiemQh4uq4G3vUra/Ws/hs9vEvL3Q== "@types/semver@^7.3.12": - version "7.3.12" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c" - integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A== + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + +"@types/triple-beam@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.2.tgz#38ecb64f01aa0d02b7c8f4222d7c38af6316fef8" + integrity sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g== "@types/winston@2.4.4": version "2.4.4" @@ -949,15 +593,15 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== +acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" @@ -987,9 +631,9 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: color-convert "^2.0.1" anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -1019,16 +663,11 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -async@^3.0.0: +async@^3.0.0, async@^3.2.0, async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== -async@^3.2.0, async@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" - integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1040,11 +679,13 @@ available-typed-arrays@^1.0.5: integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== axios@*: - version "0.25.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" - integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== + version "1.4.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== dependencies: - follow-redirects "^1.14.7" + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" axios@1.2.1: version "1.2.1" @@ -1065,16 +706,11 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -bignumber.js@9.1.1: +bignumber.js@9.1.1, bignumber.js@^9.0.1: version "9.1.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== -bignumber.js@^9.0.1: - version "9.0.2" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" - integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -1083,7 +719,7 @@ binary-extensions@^2.0.0: bintrees@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" - integrity sha1-SfiW1uhYpKSZ34XDj7OZua/4QPg= + integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw== bn.js@^4.11.9: version "4.12.0" @@ -1110,7 +746,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1120,7 +756,7 @@ braces@^3.0.1, braces@~3.0.2: brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== browser-stdout@1.3.1: version "1.3.1" @@ -1169,7 +805,7 @@ chalk@^4.0.0, chalk@^4.1.0: check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== chokidar@3.5.3, chokidar@^3.5.2: version "3.5.3" @@ -1212,7 +848,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" @@ -1220,9 +856,9 @@ color-name@^1.0.0, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.6.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.0.tgz#63b6ebd1bec11999d1df3a79a7569451ac2be8aa" - integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ== + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -1235,11 +871,6 @@ color@^3.1.3: color-convert "^1.9.3" color-string "^1.6.0" -colors@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - colorspace@1.1.x: version "1.1.4" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" @@ -1258,7 +889,7 @@ combined-stream@^1.0.8: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== core-util-is@~1.0.0: version "1.0.3" @@ -1274,7 +905,7 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -debug@4.3.4, debug@^4.3.4: +debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1288,13 +919,6 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.1, debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" @@ -1313,11 +937,12 @@ deep-is@^0.1.3: integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" delayed-stream@~1.0.0: version "1.0.0" @@ -1376,45 +1001,10 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== -es-abstract@^1.18.5: - version "1.19.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" - is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - es6-object-assign@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= + integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw== escalade@^3.1.1: version "3.1.1" @@ -1435,9 +1025,9 @@ eslint-scope@^5.1.1: estraverse "^4.1.1" eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -1454,10 +1044,10 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== eslint@8.30.0: version "8.30.0" @@ -1505,18 +1095,18 @@ eslint@8.30.0: text-table "^0.2.0" espree@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" - integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== + version "9.6.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f" + integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A== dependencies: - acorn "^8.8.0" + acorn "^8.9.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.1" esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" @@ -1542,7 +1132,7 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -ethers@5.7.2: +ethers@5.7.2, ethers@^5.4.2, ethers@^5.7.0: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -1578,87 +1168,15 @@ ethers@5.7.2: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" -ethers@^5.4.2: - version "5.5.3" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.3.tgz#1e361516711c0c3244b6210e7e3ecabf0c75fca0" - integrity sha512-fTT4WT8/hTe/BLwRUtl7I5zlpF3XC3P/Xwqxc5AIP2HGlH15qpmjs0Ou78az93b1rLITzXLFxoNX63B8ZbUd7g== - dependencies: - "@ethersproject/abi" "5.5.0" - "@ethersproject/abstract-provider" "5.5.1" - "@ethersproject/abstract-signer" "5.5.0" - "@ethersproject/address" "5.5.0" - "@ethersproject/base64" "5.5.0" - "@ethersproject/basex" "5.5.0" - "@ethersproject/bignumber" "5.5.0" - "@ethersproject/bytes" "5.5.0" - "@ethersproject/constants" "5.5.0" - "@ethersproject/contracts" "5.5.0" - "@ethersproject/hash" "5.5.0" - "@ethersproject/hdnode" "5.5.0" - "@ethersproject/json-wallets" "5.5.0" - "@ethersproject/keccak256" "5.5.0" - "@ethersproject/logger" "5.5.0" - "@ethersproject/networks" "5.5.2" - "@ethersproject/pbkdf2" "5.5.0" - "@ethersproject/properties" "5.5.0" - "@ethersproject/providers" "5.5.2" - "@ethersproject/random" "5.5.1" - "@ethersproject/rlp" "5.5.0" - "@ethersproject/sha2" "5.5.0" - "@ethersproject/signing-key" "5.5.0" - "@ethersproject/solidity" "5.5.0" - "@ethersproject/strings" "5.5.0" - "@ethersproject/transactions" "5.5.0" - "@ethersproject/units" "5.5.0" - "@ethersproject/wallet" "5.5.0" - "@ethersproject/web" "5.5.1" - "@ethersproject/wordlists" "5.5.0" - -ethers@^5.7.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.1.tgz#48c83a44900b5f006eb2f65d3ba6277047fd4f33" - integrity sha512-5krze4dRLITX7FpU8J4WscXqADiKmyeNlylmmDLbS95DaZpBhDe2YSwRQwKXWNyXcox7a3gBgm/MkGXV1O1S/Q== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.1" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + version "3.3.0" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" + integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -1674,19 +1192,19 @@ fast-json-stable-stringify@^2.0.0: fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" fecha@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce" - integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q== + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== file-entry-cache@^6.0.1: version "6.0.1" @@ -1724,29 +1242,26 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== fn.name@1.x.x: version "1.1.0" resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.7: - version "1.14.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" - integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== - follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" form-data@^4.0.0: version "4.0.0" @@ -1760,7 +1275,7 @@ form-data@^4.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.2" @@ -1780,24 +1295,17 @@ get-caller-file@^2.0.5: get-func-name@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + has-proto "^1.0.1" + has-symbols "^1.0.3" glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -1813,7 +1321,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@7.2.0, glob@^7.1.3: +glob@7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -1825,6 +1333,18 @@ glob@7.2.0, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.3: + 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.19.0: version "13.20.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" @@ -1844,30 +1364,44 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + grapheme-splitter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0: version "1.0.0" @@ -1899,7 +1433,7 @@ he@1.2.0: hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" @@ -1908,17 +1442,17 @@ hmac-drbg@^1.0.1: ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" - integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" @@ -1931,12 +1465,12 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -1951,15 +1485,6 @@ ini@^2.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -1973,13 +1498,6 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -1987,30 +1505,15 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" +is-callable@^1.1.3: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -2039,18 +1542,6 @@ is-nan@^1.2.1: call-bind "^1.0.0" define-properties "^1.1.3" -is-negative-zero@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -2066,47 +1557,20 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== - is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.3, is-typed-array@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" - integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== +is-typed-array@^1.1.10, is-typed-array@^1.1.3: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" + for-each "^0.3.3" + gopd "^1.0.1" has-tostringtag "^1.0.0" is-unicode-supported@^0.1.0: @@ -2114,27 +1578,20 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-weakref@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== js-sdsl@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.5.tgz#1ff1645e6b4d1b028cd3f862db88c9d887f26e2a" - integrity sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q== + version "4.4.1" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.1.tgz#9e3c7b566d8d9a7e1fe8fc26d00b5ab0f8918ab3" + integrity sha512-6Gsx8R0RucyePbWqPssR8DyfuXmLBooYN5cZFZKjHGnQuaf7pEzhtpceagJxVu4LqhYY5EYA7nko3FmeHZ1KbA== js-sha3@0.8.0: version "0.8.0" @@ -2156,17 +1613,17 @@ json-schema-traverse@^0.4.1: json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== jszip@^3.2.2: - version "3.7.1" - resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9" - integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg== + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== dependencies: lie "~3.3.0" pako "~1.0.2" readable-stream "~2.3.6" - set-immediate-shim "~1.0.1" + setimmediate "^1.0.5" kuler@^2.0.0: version "2.0.0" @@ -2208,32 +1665,22 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -logform@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.3.2.tgz#68babe6a74ab09a1fd15a9b1e6cbc7713d41cb5b" - integrity sha512-V6JiPThZzTsbVRspNO6TmHkR99oqYTs8fivMBYQkjZj6rxW92KxtDCPE6IkAk1DNBnYKNkjm4jYBm6JDUcyhOA== - dependencies: - colors "1.4.0" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^1.1.0" - triple-beam "^1.3.0" - -logform@^2.4.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.2.tgz#a617983ac0334d0c3b942c34945380062795b47c" - integrity sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw== +logform@^2.3.2, logform@^2.4.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b" + integrity sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg== dependencies: "@colors/colors" "1.5.0" + "@types/triple-beam" "^1.3.2" fecha "^4.2.0" ms "^2.1.1" safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== dependencies: get-func-name "^2.0.0" @@ -2250,12 +1697,12 @@ merge2@^1.3.0, merge2@^1.4.1: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" mime-db@1.52.0: version "1.52.0" @@ -2277,7 +1724,7 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== minimatch@5.0.1: version "5.0.1" @@ -2286,14 +1733,7 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^3.0.5, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -2367,7 +1807,7 @@ natural-compare-lite@^1.4.0: natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== nconf@0.12.0: version "0.12.0" @@ -2398,7 +1838,7 @@ nodemon@2.0.20: nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== dependencies: abbrev "1" @@ -2407,11 +1847,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== - object-is@^1.0.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -2420,25 +1855,15 @@ object-is@^1.0.1: call-bind "^1.0.2" define-properties "^1.1.3" -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -2450,16 +1875,16 @@ one-time@^1.0.0: fn.name "1.x.x" optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" p-limit@^3.0.2: version "3.1.0" @@ -2495,7 +1920,7 @@ path-exists@^4.0.0: path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.1.0: version "3.1.1" @@ -2512,7 +1937,7 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -2538,9 +1963,9 @@ pstree.remy@^1.1.8: integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== queue-microtask@^1.2.2: version "1.2.3" @@ -2555,18 +1980,18 @@ randombytes@^2.1.0: safe-buffer "^5.1.0" readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -2591,7 +2016,7 @@ regexpp@^3.2.0: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve-from@^4.0.0: version "4.0.0" @@ -2617,7 +2042,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: +safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -2627,15 +2052,10 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-stable-stringify@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" - integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== - safe-stable-stringify@^2.3.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.0.tgz#95fadb1bcf8057a1363e11052122f5da36a69215" - integrity sha512-eehKHKpab6E741ud7ZIMcXhKcP6TSIezPkNZhy5U8xC6+VvrRdUA2tMgxGxaGl4cz7c2Ew5+mg5+wNB16KQqrA== + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== scrypt-js@3.0.1: version "3.0.1" @@ -2645,7 +2065,7 @@ scrypt-js@3.0.1: secure-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/secure-keys/-/secure-keys-1.0.0.tgz#f0c82d98a3b139a8776a8808050b824431087fca" - integrity sha1-8MgtmKOxOah3aogIBQuCRDEIf8o= + integrity sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg== semver@^5.7.1: version "5.7.1" @@ -2653,9 +2073,9 @@ semver@^5.7.1: integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@^7.3.7: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" @@ -2671,10 +2091,10 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -set-immediate-shim@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== shebang-command@^2.0.0: version "2.0.0" @@ -2688,26 +2108,17 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" simple-update-notifier@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz#7edf75c5bdd04f88828d632f762b2bc32996a9cc" - integrity sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew== + version "1.1.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" + integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== dependencies: semver "~7.0.0" @@ -2719,7 +2130,7 @@ slash@^3.0.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" @@ -2730,22 +2141,6 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -2801,7 +2196,7 @@ text-hex@1.0.x: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== to-regex-range@^5.0.1: version "5.0.1" @@ -2817,7 +2212,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -triple-beam@^1.2.0, triple-beam@^1.3.0: +triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== @@ -2861,16 +2256,6 @@ typescript@4.8.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -2886,42 +2271,30 @@ uri-js@^4.2.2: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@^0.12.0: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== dependencies: inherits "^2.0.3" is-arguments "^1.0.4" is-generator-function "^1.0.7" is-typed-array "^1.1.3" - safe-buffer "^5.1.2" which-typed-array "^1.1.2" -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - which-typed-array@^1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" - integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" + for-each "^0.3.3" + gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.7" + is-typed-array "^1.1.10" which@^2.0.1: version "2.0.2" @@ -2930,15 +2303,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -winston-transport@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.2.tgz#554efe3fce229d046df006e0e3c411d240652e51" - integrity sha512-9jmhltAr5ygt5usgUTQbEiw/7RYXpyUbEAFRCSicIacpUzPkrnQsQZSPGEI12aLK9Jth4zNcYJx3Cvznwrl8pw== - dependencies: - logform "^2.3.2" - readable-stream "^3.4.0" - triple-beam "^1.2.0" - winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" @@ -2949,19 +2313,21 @@ winston-transport@^4.5.0: triple-beam "^1.3.0" winston@*: - version "3.4.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.4.0.tgz#7080f24b02a0684f8a37f9d5c6afb1ac23e95b84" - integrity sha512-FqilVj+5HKwCfIHQzMxrrd5tBIH10JTS3koFGbLVWBODjiIYq7zir08rFyBT4rrTYG/eaTqDcfSIbcjSM78YSw== + version "3.9.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.9.0.tgz#2bbdeb8167a75fac6d9a0c6d002890cd908016c2" + integrity sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ== dependencies: + "@colors/colors" "1.5.0" "@dabh/diagnostics" "^2.0.2" async "^3.2.3" is-stream "^2.0.0" - logform "^2.3.2" + logform "^2.4.0" one-time "^1.0.0" readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" stack-trace "0.0.x" triple-beam "^1.3.0" - winston-transport "^4.4.2" + winston-transport "^4.5.0" winston@3.8.2: version "3.8.2" @@ -2980,11 +2346,6 @@ winston@3.8.2: triple-beam "^1.3.0" winston-transport "^4.5.0" -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" @@ -3002,7 +2363,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@7.4.6: version "7.4.6" From 6b0e050eb371c391ceb5cec05a6efb162690c182 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 8 Jul 2023 14:48:52 +0700 Subject: [PATCH 002/173] fix prepare.js copyFileSync --- prepare.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prepare.js b/prepare.js index 05e12f9..70070a6 100644 --- a/prepare.js +++ b/prepare.js @@ -48,7 +48,7 @@ folders.forEach((folder) => { fs.readdirSync(folder.path).forEach((file) => { if (folder.regex.test(file)) { console.log(`copying file ${file} to ${distJsFolder}`); - fs.copyFileSync(`${folder.path}\\${file}`, `${folder.outputFile}\\${file}`); + fs.copyFileSync(`${folder.path}\/${file}`, `${folder.outputFile}\/${file}`); } }); }); From 2440cb16d699f90afc881f33a954005f2dd4505d Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 8 Jul 2023 19:05:19 +0700 Subject: [PATCH 003/173] fix maxtrade_amt typo --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 1ba8507..977a341 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -237,7 +237,7 @@ abstract class AbstractBot { this.contracts["TradePairs"].deployedContract = this.tradePair; this.minTradeAmnt = this.pairObject.mintrade_amnt; - this.maxTradeAmnt = this.pairObject.mintrade_amnt; + this.maxTradeAmnt = this.pairObject.maxtrade_amnt; this.quoteDisplayDecimals = this.pairObject.quotedisplaydecimals; this.baseDisplayDecimals = this.pairObject.basedisplaydecimals; From cdbf1b43f476f7b7f9efb0ff5ca633e4a8402968 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 9 Jul 2023 12:14:31 +0700 Subject: [PATCH 004/173] Changed portfolioRebalanceAtStart from Y/N to boolean --- services/bots/AbstractBot.ts | 2 +- services/bots/SampleBot.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 977a341..84b1801 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -48,7 +48,7 @@ abstract class AbstractBot { protected chainOrderbook: any; //orderbook from the chain protected orderUptader: NodeJS.Timeout | undefined; protected rebalancePct = 0.9; - protected portfolioRebalanceAtStart = "N"; + protected portfolioRebalanceAtStart = false; protected lastExecution: any; protected PNL: any; // Needs to be implemented protected initialDepositBase = 10000; diff --git a/services/bots/SampleBot.ts b/services/bots/SampleBot.ts index 9dc8af6..d24be0c 100644 --- a/services/bots/SampleBot.ts +++ b/services/bots/SampleBot.ts @@ -11,7 +11,7 @@ class SampleBot extends AbstractBot { constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); // Will try to rebalance the amounts in the Portfolio Contract - this.portfolioRebalanceAtStart = "Y"; + this.portfolioRebalanceAtStart = "N"; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { From 1a712774ee5db68bf065abaf33a318fcaf3e21eb Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 9 Jul 2023 12:47:50 +0700 Subject: [PATCH 005/173] Change portfolioRebalanceAtStart type from string to bool --- services/bots/AbstractBot.ts | 2 +- services/bots/LoadBot.ts | 2 +- services/bots/SampleBot.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 84b1801..7024000 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1746,7 +1746,7 @@ abstract class AbstractBot { } } } - if (this.portfolioRebalanceAtStart === "Y") { + if (this.portfolioRebalanceAtStart === true) { //BASE if ( this.contracts[this.base].portfolioTot < baseCapital * (1 - this.rebalancePct) || diff --git a/services/bots/LoadBot.ts b/services/bots/LoadBot.ts index f7a2d47..e38427e 100644 --- a/services/bots/LoadBot.ts +++ b/services/bots/LoadBot.ts @@ -15,7 +15,7 @@ class LoadBot extends AbstractBot { constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { super(botId, pairStr, privateKey, ratelimit_token); // Do not rebalance the portfolio. The tokens are expected to be in the subnet already - this.portfolioRebalanceAtStart = "N"; + this.portfolioRebalanceAtStart = false; this.washTradeCheck = false; } diff --git a/services/bots/SampleBot.ts b/services/bots/SampleBot.ts index d24be0c..cef81ba 100644 --- a/services/bots/SampleBot.ts +++ b/services/bots/SampleBot.ts @@ -11,7 +11,7 @@ class SampleBot extends AbstractBot { constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); // Will try to rebalance the amounts in the Portfolio Contract - this.portfolioRebalanceAtStart = "N"; + this.portfolioRebalanceAtStart = true; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { From cc8a145185e4aa664ae28d3f3ff533d6c4934492 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 10 Jul 2023 16:36:47 +0700 Subject: [PATCH 006/173] removed loadbot, many changes in Abstract bot, created avax_usdc which uses addLimitOrderList, added classes.ts file --- package.json | 1 + services/bots/AbstractBot.ts | 156 ++++++++------- services/bots/BotFactory.ts | 4 +- services/bots/LoadBot.ts | 361 ----------------------------------- services/bots/avax_usdc.ts | 171 +++++++++++++++++ services/bots/classes.ts | 14 ++ 6 files changed, 280 insertions(+), 427 deletions(-) delete mode 100644 services/bots/LoadBot.ts create mode 100644 services/bots/avax_usdc.ts create mode 100644 services/bots/classes.ts diff --git a/package.json b/package.json index 242a1db..ba53c17 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "sampleBot-hh": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=local-hh --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "sampleBot-dev": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=development --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "sampleBot-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", + "avax_usdc-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "loadBot": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "loadBot1": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp@1 --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "loadBot2": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp@2 --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 7024000..e447a6e 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -9,6 +9,7 @@ import { BigNumber as BigNumberEthers } from "ethers"; import axios from "axios"; import { getLogger } from "../logger"; import OrderBook from "./orderbook"; +import NewOrder from "./classes"; import ERC20ABI from "../../artifacts/contracts/ERC20.json"; import OrderBookRecordRaw from "../../models/orderBookRecordRaw"; @@ -62,6 +63,12 @@ abstract class AbstractBot { protected signature: any; protected axiosConfig: any; + protected bidSpread: any; + protected askSpread: any; + protected orderLevels: any; + protected orderLevelSpread: any; + protected orderLevelQty: any; + constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { this.logger = getLogger("Bot"); this.instanceName = botId + ":" + pairStr; @@ -415,8 +422,7 @@ abstract class AbstractBot { return new BigNumber(this.minTradeAmnt * (1 + Math.random() * 0.2)).div(price); } - // Reference implementation, it just send 6 buy limit GTC orders with prices from 94 to 100 - async addLimitOrderList() { + async addLimitOrderList(newOrders: NewOrder[]) { const clientOrderIds = []; const prices = []; const quantities = []; @@ -424,22 +430,22 @@ abstract class AbstractBot { const type2s = []; const blocknumber = (await this.contracts["SubNetProvider"].provider.getBlockNumber()) || 0; - //buy orders - for (let i = 0; i < 6; i++) { + + for (let i = 0; i < newOrders.length; i++){ const clientOrderId = await this.getClientOrderId(blocknumber, i); const priceToSend = utils.parseUnits( - (100 - i).toFixed(this.quoteDisplayDecimals), + newOrders[i].price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals ); const quantityToSend = utils.parseUnits( - (10 + i).toFixed(this.baseDisplayDecimals), + newOrders[i].quantity.toFixed(this.baseDisplayDecimals), this.contracts[this.base].tokenDetails.evmdecimals ); clientOrderIds.push(clientOrderId); prices.push(priceToSend); quantities.push(quantityToSend); - sides.push(0); + sides.push(newOrders[i].side); type2s.push(0); const order = this.makeOrder( @@ -466,6 +472,48 @@ abstract class AbstractBot { this.addOrderToMap(order); } + // //buy orders + // for (let i = 0; i < 6; i++) { + // const clientOrderId = await this.getClientOrderId(blocknumber, i); + // const priceToSend = utils.parseUnits( + // (100 - i).toFixed(this.quoteDisplayDecimals), + // this.contracts[this.quote].tokenDetails.evmdecimals + // ); + // const quantityToSend = utils.parseUnits( + // (10 + i).toFixed(this.baseDisplayDecimals), + // this.contracts[this.base].tokenDetails.evmdecimals + // ); + // clientOrderIds.push(clientOrderId); + + // prices.push(priceToSend); + // quantities.push(quantityToSend); + // sides.push(0); + // type2s.push(0); + + // const order = this.makeOrder( + // this.account, + // this.tradePairByte32, + // "", // orderid not assigned by the smart contract yet + // clientOrderId, + // priceToSend, + // 0, + // quantityToSend, + // 0, + // 1, + // 0, //Buy , Limit, GTC + // 9, //PENDING status + // 0, + // 0, + // "", + // 0, + // 0, + // 0, + // 0 + // ); + + // this.addOrderToMap(order); + // } + try { const gasest = await this.getAddOrderListGasEstimate(clientOrderIds, prices, quantities, sides, type2s); @@ -577,40 +625,14 @@ abstract class AbstractBot { utils.printBalances(this.account, this.quote, this.contracts[this.quote]); return; } - if (this.washTradeCheck) { - const myBestask = this.orderbook.bestask(); - if (myBestask && ordtype === 1) { - const order = this.orders.get(myBestask.orders[0].clientOrderId); - if (order && price.gte(order.price)) { - this.logger.warn( - `${this.instanceName} 'Wash trade not allowed. New BUY order price ${price.toFixed( - this.quoteDisplayDecimals - )} >= Best Ask ${order.price.toString()}` - ); - return; - } - } - } + this.checkWashTrade(side, price); } else { if (!funds) { this.logger.error(`${this.instanceName} Not enough funds to add SELL order`); utils.printBalances(this.account, this.base, this.contracts[this.base]); return; } - if (this.washTradeCheck) { - const myBestbid = this.orderbook.bestbid(); - if (myBestbid && ordtype === 1) { - const order = this.orders.get(myBestbid.orders[0].clientOrderId); - if (order && price.lte(order.price)) { - this.logger.warn( - `${this.instanceName} 'Wash trade not allowed. New SELL order price ${price.toFixed( - this.quoteDisplayDecimals - )} <= Best Bid ${order.price.toString()}` - ); - return; - } - } - } + this.checkWashTrade(side, price); } this.orderCount++; @@ -1306,35 +1328,8 @@ abstract class AbstractBot { } try { - if (this.washTradeCheck) { - if (order.side === 0) { - const myBestask = this.orderbook.bestask(); - if (myBestask) { - const orderBAsk = this.orders.get(myBestask.orders[0].clientOrderId); - if (orderBAsk && price.gte(orderBAsk.price)) { - this.logger.warn( - `${this.instanceName} 'Wash trade in C/R not allowed. New BUY order price ${price.toFixed( - this.quoteDisplayDecimals - )} >= Best Ask ${orderBAsk.price.toString()}` - ); - return; - } - } - } else { - const myBestbid = this.orderbook.bestbid(); - if (myBestbid) { - const orderBBid = this.orders.get(myBestbid.orders[0].clientOrderId); - if (orderBBid && price.lte(orderBBid.price)) { - this.logger.warn( - `${this.instanceName} 'Wash trade in C/R not allowed. New SELL order price ${price.toFixed( - this.quoteDisplayDecimals - )} <= Best Bid ${orderBBid.price.toString()}` - ); - return; - } - } - } - } + + this.checkWashTrade(order.side, price); const priceToSend = utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals); const quantityToSend = utils.parseUnits( @@ -1876,6 +1871,39 @@ abstract class AbstractBot { } } + async checkWashTrade(side: number, price: BigNumber) { + if (this.washTradeCheck) { + if (side === 0){ + const myBestbid = this.orderbook.bestbid(); + if (myBestbid) { + const order = this.orders.get(myBestbid.orders[0].clientOrderId); + if (order && price.lte(order.price)) { + this.logger.warn( + `${this.instanceName} 'Wash trade not allowed. New SELL order price ${price.toFixed( + this.quoteDisplayDecimals + )} <= Best Bid ${order.price.toString()}` + ); + return; + } + } + } else if (side === 1){ + const myBestbid = this.orderbook.bestbid(); + if (myBestbid) { + const order = this.orders.get(myBestbid.orders[0].clientOrderId); + if (order && price.lte(order.price)) { + this.logger.warn( + `${this.instanceName} 'Wash trade not allowed. New SELL order price ${price.toFixed( + this.quoteDisplayDecimals + )} <= Best Bid ${order.price.toString()}` + ); + return; + } + } + } + + } + } + async cleanUpAndExit() { if (!this.cleanupCalled) { this.logger.warn(`${this.instanceName} === Process Exit Called === `); diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index 731e682..6c5dfaa 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -2,8 +2,8 @@ import SampleBot from "./SampleBot"; -import LoadBot from "./LoadBot"; -const Bot:any = { SampleBot, LoadBot}; +import avax_usdc from "./avax_usdc"; +const Bot:any = { SampleBot, avax_usdc}; module.exports = { createBot(type:any, attributes:any) { diff --git a/services/bots/LoadBot.ts b/services/bots/LoadBot.ts deleted file mode 100644 index e38427e..0000000 --- a/services/bots/LoadBot.ts +++ /dev/null @@ -1,361 +0,0 @@ -import utils from "../utils"; -import BigNumber from "bignumber.js"; -import AbstractBot from "./AbstractBot"; -import { getConfig } from "../../config"; -import { Performance } from "perf_hooks"; -import axios from "axios"; - -const apiUrl = getConfig("API_URL") + "trading/"; -class LoadBot extends AbstractBot { - protected marketPrice = new BigNumber(17); //AVAX/USDC - protected baseUsd = 17; //AVAX - protected quoteUsd = 1; //USDC - protected capitalASideUSD = 300; - - constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { - super(botId, pairStr, privateKey, ratelimit_token); - // Do not rebalance the portfolio. The tokens are expected to be in the subnet already - this.portfolioRebalanceAtStart = false; - this.washTradeCheck = false; - } - - async saveBalancestoDb(balancesRefreshed: boolean): Promise { - this.logger.info(`${this.instanceName} Save Balances somewhere if needed`); - } - - async initialize(): Promise { - const initializing = await super.initialize(); - if (initializing) { - await this.getNewMarketPrice(); - - this.interval = 15000; //Min 10 seconds - - this.minTradeAmnt = this.pairObject.mintrade_amnt * 1.1; - this.maxTradeAmnt = this.pairObject.mintrade_amnt * 5; - - return true; - } else { - return false; - } - } - - async startOrderUpdater() { - if (this.status) { - //Enable the next line if you need the bot to run continuously - this.orderUptader = setTimeout(() => this.updateOrders(), this.interval); - } else { - this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); - } - } - - async updateOrders() { - if (this.orderUptader != undefined) { - clearTimeout(this.orderUptader); - } - - await this.cancelOrderList([], 100); - // // this will refill the gas tank if running low - // await this.cancelIndividualOrders(10); - - try { - //await this.addSingleOrders(3); - // await this.addLimitOrderList(20); - - // await this.addSingleOrders(1, 1, 1000, 0.15); // Sell 1500 at 13 - // await this.addSingleOrders(1, 0, 1000, 0.17); // Buy 1500 at 13 - - // await this.addSingleOrders(1, 1, 5, 15); // Sell 1500 at 13 - // await this.addSingleOrders(1, 0, 5, 17); // Buy 1500 at 13 - - //await this.addLimitOrderList(100, 0); // 100 random BUY orders - - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - } catch (error) { - this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); - //process.exit(1); - } finally { - // Enable the next line if you need the bot to run continuously - this.startOrderUpdater(); - } - } - - async cancelIndividualOrders(nbrofOrderstoCancel: number) { - let i = 0; - const promises = []; - for (const order of this.orders.values()) { - promises.push(this.cancelOrder(order)); - i++; - if (i >= nbrofOrderstoCancel) { - break; - } - } - await Promise.all(promises); - } - - async generateOrders(nbrofOrdersToAdd: number, addToMap = true, side = 99, quantity = 0, price = 0) { - const clientOrderIds = []; - const prices = []; - const quantities = []; - const sides = []; - const type2s = []; - const marketpx = await this.getNewMarketPrice(); - const blocknumber = (await this.contracts["SubNetProvider"].provider.getBlockNumber()) || 0; - - let randomSide; - - for (let i = 0; i < nbrofOrdersToAdd; i++) { - const clientOrderId = await this.getClientOrderId(blocknumber, i); - const pxdivisor = this.base === "tALOT" ? 2000 : 20; - let px = marketpx; - - if (price > 0) { - px = BigNumber(price); - } - - if (quantity === 0) { - // quantity not given - switch (this.base) { - case "tALOT": { - quantity = utils.randomFromIntervalPositive(5, 50, this.baseDisplayDecimals); - break; - } - case "tAVAX": { - quantity = utils.randomFromIntervalPositive(0.05, 0.5, this.baseDisplayDecimals); - break; - } - case "WETH.e": { - quantity = utils.randomFromIntervalPositive(0.03, 0.05, this.baseDisplayDecimals); - break; - } - } - } - - if (side > 1) { - // if side is not given - px = i % 2 == 0 ? marketpx.minus(i / pxdivisor) : marketpx.plus(i / pxdivisor); - randomSide = i % 2; - } else { - randomSide = side; - } - - const type = 1; - const type2 = 0; - const priceToSend = utils.parseUnits(px.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals); - const quantityToSend = utils.parseUnits( - quantity.toFixed(this.baseDisplayDecimals), - this.contracts[this.base].tokenDetails.evmdecimals - ); - - clientOrderIds.push(clientOrderId); - prices.push(priceToSend); - quantities.push(quantityToSend); - sides.push(randomSide); - type2s.push(type2); - - if (addToMap) { - const order = this.makeOrder( - this.account, - this.tradePairByte32, - "", // orderid not assigned by the smart contract yet - clientOrderId, - priceToSend, - 0, - quantityToSend, - randomSide, // 0-Buy - type, - type2, // Limit, GTC - 9, //PENDING status - 0, - 0, - "", - 0, - 0, - 0, - 0 - ); - - this.addOrderToMap(order); - } - } - - return { clientOrderIds, prices, quantities, sides, type2s }; - } - - async addSingleOrders(nbrofOrdersToAdd: number, side = 99, quantity = 0, price = 0) { - const orders = await this.generateOrders(nbrofOrdersToAdd, false, side, quantity, price); - - const promises = []; - for (let i = 0; i < orders.clientOrderIds.length; i++) { - promises.push( - this.addOrder( - orders.sides[i], - BigNumber(utils.formatUnits(orders.quantities[i], this.contracts[this.base].tokenDetails.evmdecimals)), - BigNumber(utils.formatUnits(orders.prices[i], this.contracts[this.quote].tokenDetails.evmdecimals)), - 1, - orders.type2s[i] - ) - ); - } - - await Promise.all(promises); - } - - async addLimitOrderList(nbrofOrdersToAdd = 10, side = 99, quantity = 0, price = 0) { - const startTime = performance.now(); - const orders = await this.generateOrders(nbrofOrdersToAdd, true, side, quantity, price); - const endTime2 = performance.now(); - - console.log(`Generate Orders took ${(endTime2 - startTime) / 1000} seconds`); - try { - const gasest = await this.getAddOrderListGasEstimate( - orders.clientOrderIds, - orders.prices, - orders.quantities, - orders.sides, - orders.type2s - ); - - this.logger.warn(`${this.instanceName} Gas Est ${gasest.toString()}`); - - const tx = await this.tradePair.addLimitOrderList( - this.tradePairByte32, - orders.clientOrderIds, - orders.prices, - orders.quantities, - orders.sides, - orders.type2s, - await this.getOptions(this.contracts["SubNetProvider"], gasest) - ); - const orderLog = await tx.wait(); - - //Add the order to the map quickly to be replaced by the event fired by the blockchain that will follow. - if (orderLog) { - for (const _log of orderLog.events) { - if (_log.event) { - if (_log.event === "OrderStatusChanged") { - if (_log.args.traderaddress === this.account && _log.args.pair === this.tradePairByte32) { - await this.processOrders( - _log.args.version, - this.account, - _log.args.pair, - _log.args.orderId, - _log.args.clientOrderId, - _log.args.price, - _log.args.totalamount, - _log.args.quantity, - _log.args.side, - _log.args.type1, - _log.args.type2, - _log.args.status, - _log.args.quantityfilled, - _log.args.totalfee, - _log.args.code, - _log - ); - } - } - } - } - } - } catch (error: any) { - for (const clientOrderId of orders.clientOrderIds) { - //Need to remove the pending order from the memory if there is any error - this.removeOrderByClOrdId(clientOrderId); - } - - const nonceErr = "Nonce too high"; - const idx = error.message.indexOf(nonceErr); - if (error.code === "NONCE_EXPIRED" || idx > -1) { - this.logger.warn(`${this.instanceName} addLimitOrderList error: Invalid Nonce `); - - await this.correctNonce(this.contracts["SubNetProvider"]); - } else { - const reason = await this.getRevertReason(error); - if (reason) { - this.logger.warn(`${this.instanceName} addLimitOrderList error: Revert Reason ${reason}`); - } else { - this.logger.error(`${this.instanceName} addLimitOrderList error:`, error); - } - } - } finally { - const endTime = performance.now(); - console.log(`Send List Orders took ${(endTime - endTime2) / 1000} seconds`); - } - } - - getQuantity(price: BigNumber, side: number) { - return new BigNumber(this.minTradeAmnt).div(price); - } - - getPrice(side: number): BigNumber { - return this.marketPrice; - } - - // Update the marketPrice from an outside source - async getNewMarketPrice() { - try { - let px; - - switch (this.base) { - case "tALOT": { - px = utils.randomFromIntervalPositive(0.16, 0.162, this.quoteDisplayDecimals); - break; - } - case "tAVAX": { - px = utils.randomFromIntervalPositive(16, 16.3, this.quoteDisplayDecimals); - break; - } - case "WETH.e": { - px = utils.randomFromIntervalPositive(1600, 1620, this.quoteDisplayDecimals); - break; - } - default: { - px = utils.randomFromIntervalPositive(16, 16.3, this.quoteDisplayDecimals); - } - } - - this.setMarketPrice(px); - - // this.baseUsd = PriceService.prices[this.priceSymbolPair.base]; - // this.quoteUsd = PriceService.prices[this.priceSymbolPair.quote]; - - this.baseUsd = px; //AVAX - this.quoteUsd = 1; //USDC - } catch (error: any) { - this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); - } - return this.marketPrice; - } - - setMarketPrice(price: number) { - this.marketPrice = new BigNumber(price); - } - - async getAlotPrice(): Promise { - let alotprice = 0.25; - try { - alotprice = 0.25; // FIXME Implement your own price source to get the ALOT price - } catch (error) { - this.logger.error(`${this.instanceName} Error during getAlotPrice`, error); - } - return alotprice; - } - - getBaseCapital(): number { - if (this.baseUsd) { - return parseFloat((this.capitalASideUSD / this.baseUsd).toFixed(this.baseDisplayDecimals)); - } else { - return this.initialDepositBase; - } - } - - getQuoteCapital(): number { - if (this.quoteUsd) { - return parseFloat((this.capitalASideUSD / this.quoteUsd).toFixed(this.quoteDisplayDecimals)); - } else { - return this.initialDepositQuote; - } - } -} - -export default LoadBot; diff --git a/services/bots/avax_usdc.ts b/services/bots/avax_usdc.ts new file mode 100644 index 0000000..755080f --- /dev/null +++ b/services/bots/avax_usdc.ts @@ -0,0 +1,171 @@ +import axios from "axios"; +import utils from "../utils"; +import BigNumber from "bignumber.js"; +import AbstractBot from "./AbstractBot"; +import NewOrder from "./classes"; + +class avax_usdc extends AbstractBot { + protected marketPrice = new BigNumber(17); //AVAX/USDC + protected baseUsd = 13; //AVAX + protected quoteUsd = 1; //USDC + protected capitalASideUSD = 300; + protected counter = 0; + + constructor(botId: number, pairStr: string, privateKey: string) { + super(botId, pairStr, privateKey); + // Will try to rebalance the amounts in the Portfolio Contract + this.portfolioRebalanceAtStart = false; + this.bidSpread = 0.3; + this.askSpread = 0.3; + this.orderLevels = 2; + this.orderLevelSpread = 0.05; + this.orderLevelQty = 0.5; + } + + async saveBalancestoDb(balancesRefreshed: boolean): Promise { + this.logger.info(`${this.instanceName} Save Balances somewhere if needed`); + } + + async initialize(): Promise { + const initializing = await super.initialize(); + if (initializing) { + await this.getNewMarketPrice(); + + this.interval = 10000; //Min 10 seconds + + // this.minTradeAmnt = this.pairObject.mintrade_amnt * 1.1; + // this.maxTradeAmnt = this.pairObject.mintrade_amnt * 5; + + // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc + //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); + + return true; + } else { + return false; + } + } + + async startOrderUpdater() { + if (this.status) { + // Sleep 30 seconds initially if rebalancing portfolio + if (this.portfolioRebalanceAtStart){ + await utils.sleep(3000); + } + + this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); + //const bookinChain = await this.getBookfromChain(); + + //Get rid of any order that is outstanding on this account if needed. + //if you have more than 10-15 outstanding orders on this pair, this function may run out of gas + // use this.cancelAllIndividually() instead. + await this.cancelOrderList([], 100); + + // ------------ Create and Send Initial Order List ------------ // + + const nbrofOrders = this.orderLevels * 2; + const halfofOrders = nbrofOrders / 2; + const quantity = new BigNumber(0.5); + const marketPrice = this.getPrice(1).toNumber(); + const initialBidPrice = marketPrice * (1-this.bidSpread/100); + const initialAskPrice = marketPrice * (1+this.askSpread/100); + + let newOrderList : NewOrder[] = []; + for (let i = 0; i < halfofOrders; i++) { + let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); + newOrderList.push(new NewOrder(0,quantity,bidPrice)); + } + for (let i = 0; i < halfofOrders; i++) { + let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))) + newOrderList.push(new NewOrder(1,quantity,askPrice)); + } + + this.addLimitOrderList(newOrderList); + + // ------------ Begin Order Updater ------------ // + + this.updateOrders(); + + } else { + this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); + } + } + + async updateOrders() { + if (this.orderUptader != undefined) { + clearTimeout(this.orderUptader); + } + + try { + console.log("000000000000000 COUNTER:",this.counter); + this.counter ++; + + this.logger.debug(`orderbook:${JSON.stringify(this.getOrderBook())}`); + + } catch (error) { + this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); + process.exit(1); + } finally { + + // Wait before updating orders again + await utils.sleep(this.interval); + //Update Orders Again + this.updateOrders(); + } + } + + getQuantity(price: BigNumber, side: number) { + return new BigNumber(this.minTradeAmnt).div(price); + } + + getPrice(side: number): BigNumber { + return this.marketPrice; + } + + // Update the marketPrice from an outside source + async getNewMarketPrice() { + try { + // let response_avax = await axios.get('http://localhost/avax_usd'); + this.baseUsd = 12; //response_avax.data; //AVAX + + // let response_usdc = await axios.get('http://localhost/usdc_usd'); + this.quoteUsd = 1; //response_usdc.data; //USDC + + this.setMarketPrice(this.baseUsd/this.quoteUsd); + } catch (error: any) { + this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); + } + return this.marketPrice; + } + + setMarketPrice(price: number) { + this.marketPrice = new BigNumber(price); + } + + async getAlotPrice(): Promise { + let alotprice = 0.25; + try { + alotprice = 0.25; // FIXME Implement your own price source to get the ALOT price + } catch (error) { + this.logger.error(`${this.instanceName} Error during getAlotPrice`, error); + } + return alotprice; + } + + getBaseCapital(): number { + if (this.baseUsd) { + return parseFloat((this.capitalASideUSD / this.baseUsd).toFixed(this.baseDisplayDecimals)); + } else { + return this.initialDepositBase; + } + } + + getQuoteCapital(): number { + if (this.quoteUsd) { + return parseFloat((this.capitalASideUSD / this.quoteUsd).toFixed(this.quoteDisplayDecimals)); + } else { + return this.initialDepositQuote; + } + } +} + +export default avax_usdc; diff --git a/services/bots/classes.ts b/services/bots/classes.ts new file mode 100644 index 0000000..5dcd0ae --- /dev/null +++ b/services/bots/classes.ts @@ -0,0 +1,14 @@ +import { BigNumber } from "bignumber.js"; + +class NewOrder { + public side: number; + public quantity: BigNumber; + public price: BigNumber; + constructor(side: number, quantity: BigNumber, price: BigNumber) { + this.side = side; + this.quantity = quantity; + this.price = price; + } +} + +export default NewOrder; From e639d621706a93cb20ba293bdd6cabbd93e1c9e9 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 11 Jul 2023 00:38:28 +0700 Subject: [PATCH 007/173] initial addlimitorderlists working with getQty and price levels --- services/bots/AbstractBot.ts | 52 +++------------- services/bots/SampleBot.ts | 6 +- services/bots/avax_usdc.ts | 114 ++++++++++++++++++++++++++++++----- 3 files changed, 108 insertions(+), 64 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index e447a6e..29ce79f 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -47,7 +47,7 @@ abstract class AbstractBot { protected interval = 20000; protected orderbook: any; //local orderbook to keep track of my own orders ONLY protected chainOrderbook: any; //orderbook from the chain - protected orderUptader: NodeJS.Timeout | undefined; + protected orderUpdater: NodeJS.Timeout | undefined; protected rebalancePct = 0.9; protected portfolioRebalanceAtStart = false; protected lastExecution: any; @@ -336,8 +336,8 @@ abstract class AbstractBot { const savetoDb = this.status; this.logger.warn(`${this.instanceName} Stoppig bot...`); this.status = false; - if (this.orderUptader !== undefined) { - clearTimeout(this.orderUptader); + if (this.orderUpdater !== undefined) { + clearTimeout(this.orderUpdater); } if (this.getSettingValue("CANCEL_ALL_AT_STOP") === "Y") { this.cancelOrderList() @@ -472,51 +472,13 @@ abstract class AbstractBot { this.addOrderToMap(order); } - // //buy orders - // for (let i = 0; i < 6; i++) { - // const clientOrderId = await this.getClientOrderId(blocknumber, i); - // const priceToSend = utils.parseUnits( - // (100 - i).toFixed(this.quoteDisplayDecimals), - // this.contracts[this.quote].tokenDetails.evmdecimals - // ); - // const quantityToSend = utils.parseUnits( - // (10 + i).toFixed(this.baseDisplayDecimals), - // this.contracts[this.base].tokenDetails.evmdecimals - // ); - // clientOrderIds.push(clientOrderId); - - // prices.push(priceToSend); - // quantities.push(quantityToSend); - // sides.push(0); - // type2s.push(0); - - // const order = this.makeOrder( - // this.account, - // this.tradePairByte32, - // "", // orderid not assigned by the smart contract yet - // clientOrderId, - // priceToSend, - // 0, - // quantityToSend, - // 0, - // 1, - // 0, //Buy , Limit, GTC - // 9, //PENDING status - // 0, - // 0, - // "", - // 0, - // 0, - // 0, - // 0 - // ); - - // this.addOrderToMap(order); - // } - try { + console.log("GETTING GAS ESTIMATION", prices, quantities, sides); + const gasest = await this.getAddOrderListGasEstimate(clientOrderIds, prices, quantities, sides, type2s); + console.log("SENDING ORDER LIST"); + this.logger.warn(`${this.instanceName} Gas Est ${gasest.toString()}`); const tx = await this.tradePair.addLimitOrderList( this.tradePairByte32, diff --git a/services/bots/SampleBot.ts b/services/bots/SampleBot.ts index cef81ba..bd9dae3 100644 --- a/services/bots/SampleBot.ts +++ b/services/bots/SampleBot.ts @@ -40,7 +40,7 @@ class SampleBot extends AbstractBot { async startOrderUpdater() { if (this.status) { // Enable the next line if you need the bot to run continuously - // this.orderUptader = setTimeout( () => this.updateOrders(), this.interval ); + // this.orderUpdater = setTimeout( () => this.updateOrders(), this.interval ); // Comment out if you need the bot to run continuously this.updateOrders(); } else { @@ -49,8 +49,8 @@ class SampleBot extends AbstractBot { } async updateOrders() { - if (this.orderUptader != undefined) { - clearTimeout(this.orderUptader); + if (this.orderUpdater != undefined) { + clearTimeout(this.orderUpdater); } try { diff --git a/services/bots/avax_usdc.ts b/services/bots/avax_usdc.ts index 755080f..65a0198 100644 --- a/services/bots/avax_usdc.ts +++ b/services/bots/avax_usdc.ts @@ -3,6 +3,7 @@ import utils from "../utils"; import BigNumber from "bignumber.js"; import AbstractBot from "./AbstractBot"; import NewOrder from "./classes"; +import { error } from "console"; class avax_usdc extends AbstractBot { protected marketPrice = new BigNumber(17); //AVAX/USDC @@ -19,7 +20,7 @@ class avax_usdc extends AbstractBot { this.askSpread = 0.3; this.orderLevels = 2; this.orderLevelSpread = 0.05; - this.orderLevelQty = 0.5; + this.orderLevelQty = BigNumber(10); } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -62,24 +63,37 @@ class avax_usdc extends AbstractBot { // ------------ Create and Send Initial Order List ------------ // - const nbrofOrders = this.orderLevels * 2; - const halfofOrders = nbrofOrders / 2; - const quantity = new BigNumber(0.5); const marketPrice = this.getPrice(1).toNumber(); const initialBidPrice = marketPrice * (1-this.bidSpread/100); const initialAskPrice = marketPrice * (1+this.askSpread/100); + let bidsEnroute = 0; + let asksEnRoute = 0; let newOrderList : NewOrder[] = []; - for (let i = 0; i < halfofOrders; i++) { - let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); - newOrderList.push(new NewOrder(0,quantity,bidPrice)); + // ------- SET BIDS --------- // + for (let i = 0; i < this.orderLevels; i++) { + let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + bidsEnroute += bidQty.toNumber(); + console.log("BID LEVEL ",i,": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); + newOrderList.push(new NewOrder(0,bidQty,bidPrice)); + } } - for (let i = 0; i < halfofOrders; i++) { - let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))) - newOrderList.push(new NewOrder(1,quantity,askPrice)); + + // ------- SET ASKS --------- // + for (let i = 0; i < this.orderLevels; i++) { + let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); + let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.base].portfolioTot - asksEnRoute)); + console.log("ASK LEVEL ",i,": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + asksEnRoute += askQty.toNumber(); + newOrderList.push(new NewOrder(1,askQty,askPrice)); + } } - this.addLimitOrderList(newOrderList); + console.log("NEW ORDER LIST:",newOrderList); + await this.addLimitOrderList(newOrderList); // ------------ Begin Order Updater ------------ // @@ -91,13 +105,47 @@ class avax_usdc extends AbstractBot { } async updateOrders() { - if (this.orderUptader != undefined) { - clearTimeout(this.orderUptader); + if (this.orderUpdater != undefined) { + clearTimeout(this.orderUpdater); } try { - console.log("000000000000000 COUNTER:",this.counter); this.counter ++; + console.log("000000000000000 COUNTER:",this.counter); + + + const marketPrice = this.getPrice(1).toNumber(); + const initialBidPrice = marketPrice * (1-this.bidSpread/100); + const initialAskPrice = marketPrice * (1+this.askSpread/100); + + let bids = sortOrders(this.orderbook.state().bids, "price", "descending"); + let asks = sortOrders(this.orderbook.state().asks, "price", "ascending"); + + let baseEnRoute = 0; + let quoteEnRoute = 0; + + + bids.forEach((e: any,i: number) => { + let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.base].portfolioTot + (e.quantity * bidPrice.toNumber()) - quoteEnRoute)); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + quoteEnRoute += bidQty.toNumber(); + this.cancelReplaceOrder(e,bidPrice,bidQty); + } else { + return; + } + }) + + asks.forEach((e: any,i: number) => { + let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); + let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.quote].portfolioTot + e.quantity - baseEnRoute)); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + baseEnRoute += askQty.toNumber(); + this.cancelReplaceOrder(e,askPrice,askQty); + } + }) + + this.logger.debug(`orderbook:${JSON.stringify(this.getOrderBook())}`); @@ -108,13 +156,28 @@ class avax_usdc extends AbstractBot { // Wait before updating orders again await utils.sleep(this.interval); + await this.cancelOrderList([], 100); //Update Orders Again this.updateOrders(); } } - getQuantity(price: BigNumber, side: number) { - return new BigNumber(this.minTradeAmnt).div(price); + getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { + if (side === 0){ + console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",(level+1) * this.orderLevelQty.toNumber()) + if ((level+1) * this.orderLevelQty.toNumber() < availableFunds){ + return (level+1) * this.orderLevelQty.toNumber(); + } else if (availableFunds > this.minTradeAmnt * 1.1){ + return availableFunds*.9; + } else { return 0;} + } else if (side === 1) { + console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",(level+1) * this.orderLevelQty.toNumber()) + if ((level+1) * this.orderLevelQty.toNumber() < availableFunds){ + return (level+1) * this.orderLevelQty.toNumber(); + } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 1.1){ + return availableFunds * .9; + } else {return 0;} + } else { return 0;} } getPrice(side: number): BigNumber { @@ -166,6 +229,25 @@ class avax_usdc extends AbstractBot { return this.initialDepositQuote; } } + } +const sortOrders = (arr: any, propertyName: any, order: string = 'ascending') => { + const sortedArr = arr.sort((a: any, b: any) => { + if (a[propertyName] < b[propertyName]) { + return -1; + } + if (a[propertyName] > b[propertyName]) { + return 1; + } + return 0; + }); + + if (order === 'descending') { + return sortedArr.reverse(); + } + + return sortedArr; +}; + export default avax_usdc; From 435b99cb3c8e537807f9cbf7cd84bad6adfbd721 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 11 Jul 2023 11:20:32 +0700 Subject: [PATCH 008/173] Move initial orders logic. Replaces all bids or asks when one of the order levels is missing --- services/bots/AbstractBot.ts | 3 - services/bots/avax_usdc.ts | 117 +++++++++++++++++++---------------- 2 files changed, 65 insertions(+), 55 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 29ce79f..9bf2378 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -473,12 +473,9 @@ abstract class AbstractBot { } try { - console.log("GETTING GAS ESTIMATION", prices, quantities, sides); const gasest = await this.getAddOrderListGasEstimate(clientOrderIds, prices, quantities, sides, type2s); - console.log("SENDING ORDER LIST"); - this.logger.warn(`${this.instanceName} Gas Est ${gasest.toString()}`); const tx = await this.tradePair.addLimitOrderList( this.tradePairByte32, diff --git a/services/bots/avax_usdc.ts b/services/bots/avax_usdc.ts index 65a0198..98a4101 100644 --- a/services/bots/avax_usdc.ts +++ b/services/bots/avax_usdc.ts @@ -62,38 +62,7 @@ class avax_usdc extends AbstractBot { await this.cancelOrderList([], 100); // ------------ Create and Send Initial Order List ------------ // - - const marketPrice = this.getPrice(1).toNumber(); - const initialBidPrice = marketPrice * (1-this.bidSpread/100); - const initialAskPrice = marketPrice * (1+this.askSpread/100); - let bidsEnroute = 0; - let asksEnRoute = 0; - - let newOrderList : NewOrder[] = []; - // ------- SET BIDS --------- // - for (let i = 0; i < this.orderLevels; i++) { - let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); - if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - bidsEnroute += bidQty.toNumber(); - console.log("BID LEVEL ",i,": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); - newOrderList.push(new NewOrder(0,bidQty,bidPrice)); - } - } - - // ------- SET ASKS --------- // - for (let i = 0; i < this.orderLevels; i++) { - let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); - let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.base].portfolioTot - asksEnRoute)); - console.log("ASK LEVEL ",i,": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); - if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - asksEnRoute += askQty.toNumber(); - newOrderList.push(new NewOrder(1,askQty,askPrice)); - } - } - - console.log("NEW ORDER LIST:",newOrderList); - await this.addLimitOrderList(newOrderList); + await this.placeInitialOrders() // ------------ Begin Order Updater ------------ // @@ -112,7 +81,6 @@ class avax_usdc extends AbstractBot { try { this.counter ++; console.log("000000000000000 COUNTER:",this.counter); - const marketPrice = this.getPrice(1).toNumber(); const initialBidPrice = marketPrice * (1-this.bidSpread/100); @@ -124,26 +92,33 @@ class avax_usdc extends AbstractBot { let baseEnRoute = 0; let quoteEnRoute = 0; + if (bids.length < this.orderLevels){ + this.placeInitialOrders(true,false); + } else { + bids.forEach((e: any,i: number) => { + let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.base].portfolioTot + (e.quantity * bidPrice.toNumber()) - quoteEnRoute)); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + quoteEnRoute += bidQty.toNumber(); + this.cancelReplaceOrder(e,bidPrice,bidQty); + } else { + return; + } + }) + } - bids.forEach((e: any,i: number) => { - let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.base].portfolioTot + (e.quantity * bidPrice.toNumber()) - quoteEnRoute)); - if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - quoteEnRoute += bidQty.toNumber(); - this.cancelReplaceOrder(e,bidPrice,bidQty); - } else { - return; - } - }) - - asks.forEach((e: any,i: number) => { - let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); - let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.quote].portfolioTot + e.quantity - baseEnRoute)); - if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - baseEnRoute += askQty.toNumber(); - this.cancelReplaceOrder(e,askPrice,askQty); - } - }) + if (asks.length < this.orderLevels){ + this.placeInitialOrders(false,true); + } else { + asks.forEach((e: any,i: number) => { + let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); + let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.quote].portfolioTot + e.quantity - baseEnRoute)); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + baseEnRoute += askQty.toNumber(); + this.cancelReplaceOrder(e,askPrice,askQty); + } + }) + } @@ -162,6 +137,44 @@ class avax_usdc extends AbstractBot { } } + async placeInitialOrders(setBids: boolean = true, setAsks: boolean = true){ + const marketPrice = this.getPrice(1).toNumber(); + const initialBidPrice = marketPrice * (1-this.bidSpread/100); + const initialAskPrice = marketPrice * (1+this.askSpread/100); + let newOrderList : NewOrder[] = []; + // --------------- SET BIDS --------------- // + if (setBids){ + let bidsEnroute = 0; + for (let i = 0; i < this.orderLevels; i++) { + let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + bidsEnroute += bidQty.toNumber(); + console.log("BID LEVEL ",i,": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); + newOrderList.push(new NewOrder(0,bidQty,bidPrice)); + } + } + } + + // --------------- SET ASKS --------------- // + if (setAsks){ + let asksEnRoute = 0; + for (let i = 0; i < this.orderLevels; i++) { + let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); + let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.base].portfolioTot - asksEnRoute)); + console.log("ASK LEVEL ",i,": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + asksEnRoute += askQty.toNumber(); + newOrderList.push(new NewOrder(1,askQty,askPrice)); + } + } + } + + console.log("NEW ORDER LIST:",newOrderList); + // --------------- EXECUTE ORDERS --------------- // + await this.addLimitOrderList(newOrderList); + } + getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",(level+1) * this.orderLevelQty.toNumber()) From e044a2e870b70612cf17a996df11aab112a948a3 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Thu, 13 Jul 2023 11:40:32 +0700 Subject: [PATCH 009/173] initial orders, update orders, getQty, cancelReplace all working for bids --- services/bots/AbstractBot.ts | 146 +++++++++++++-------------- services/bots/BotFactory.ts | 6 +- services/bots/SampleBot.ts | 186 ----------------------------------- services/bots/avax_usdc.ts | 182 ++++++++++++++++++++-------------- services/bots/classes.ts | 4 +- 5 files changed, 182 insertions(+), 342 deletions(-) delete mode 100644 services/bots/SampleBot.ts diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 9bf2378..ded1619 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -339,45 +339,27 @@ abstract class AbstractBot { if (this.orderUpdater !== undefined) { clearTimeout(this.orderUpdater); } - if (this.getSettingValue("CANCEL_ALL_AT_STOP") === "Y") { - this.cancelOrderList() - .then(() => { - this.logger.warn(`${this.instanceName} Waiting 5 seconds before removing order listeners"...`); - setTimeout(async () => { - if (savetoDb) { - await this.saveBalancestoDb(false); - } - if (this.PNL) { - this.PNL.reset(); - } - if (this.filter) { - //Give 5 seconds before removing listeners - this.tradePair.removeAllListeners(); - this.filter = undefined; - this.logger.warn(`${this.instanceName} Removed order listeners`); - } - }, 5000); - }) - .catch((e: any) => { - this.logger.error(`${this.instanceName} problem in Bot Stop + ${e.message}`); - }); - } else { - this.logger.warn(`${this.instanceName} Waiting 5 seconds before removing order listeners"...`); - setTimeout(async () => { - if (savetoDb) { - await this.saveBalancestoDb(false); - } - if (this.PNL) { - this.PNL.reset(); - } - if (this.filter) { - //Give 5 seconds before removing listeners - this.tradePair.removeAllListeners(); - this.filter = undefined; - this.logger.warn(`${this.instanceName} Removed order listeners`); - } - }, 5000); - } + this.cancelOrderList() + .then(() => { + this.logger.warn(`${this.instanceName} Waiting 5 seconds before removing order listeners"...`); + setTimeout(async () => { + if (savetoDb) { + await this.saveBalancestoDb(false); + } + if (this.PNL) { + this.PNL.reset(); + } + if (this.filter) { + //Give 5 seconds before removing listeners + this.tradePair.removeAllListeners(); + this.filter = undefined; + this.logger.warn(`${this.instanceName} Removed order listeners`); + } + }, 5000); + }) + .catch((e: any) => { + this.logger.error(`${this.instanceName} problem in Bot Stop + ${e.message}`); + }); } getSettingValue(settingname: string) { @@ -456,7 +438,7 @@ abstract class AbstractBot { priceToSend, 0, quantityToSend, - 0, + newOrders[i].side, 1, 0, //Buy , Limit, GTC 9, //PENDING status @@ -466,7 +448,8 @@ abstract class AbstractBot { 0, 0, 0, - 0 + 0, + newOrders[i].level, ); this.addOrderToMap(order); @@ -548,7 +531,7 @@ abstract class AbstractBot { } } - async addOrder(side: number, qty: BigNumber | undefined, px: BigNumber | undefined, ordtype = 1, ordType2 = 0) { + async addOrder(side: number, qty: BigNumber | undefined, px: BigNumber | undefined, ordtype = 1, ordType2 = 0, level: number) { // LIMIT ORDER & GTC) if (!this.status) { return; @@ -632,7 +615,8 @@ abstract class AbstractBot { 0, 0, 0, - 0 + 0, + level, ); this.addOrderToMap(order); @@ -726,7 +710,7 @@ abstract class AbstractBot { } const timestamp = new Date().toISOString(); if (this.account) { - const id = eutils.toUtf8Bytes(`${this.account}${blocknumber}${timestamp}${counter}`); + const id = eutils.toUtf8Bytes(`${this.account}${this.tradePairByte32}${blocknumber}${timestamp}${counter}`); return eutils.keccak256(id); } return ""; @@ -955,7 +939,8 @@ abstract class AbstractBot { blocknbr: any, gasUsed: any, gasPrice: any, - cumulativeGasUsed: any + cumulativeGasUsed: any, + level: number = 0, ): any { return new Order({ id, @@ -979,7 +964,8 @@ abstract class AbstractBot { blocknbr, gasUsed, gasPrice: utils.formatUnits(gasPrice, 9), - cumulativeGasUsed + cumulativeGasUsed, + level, }); } @@ -1112,7 +1098,7 @@ abstract class AbstractBot { } const existingOrder = this.orders.get(order.clientOrderId); if (existingOrder) { - if (order.quantityfilled.gt(existingOrder.quantityfilled)) { + if (order.quantityfilled && order.quantityfilled.gt(existingOrder.quantityfilled)) { this.setLastExecution(order, order.quantityfilled.minus(existingOrder.quantityfilled).toNumber(), order.side === 0 ? 1 : 0); } this.orders.delete(order.clientOrderId); @@ -1260,14 +1246,14 @@ abstract class AbstractBot { } else { const reason = await this.getRevertReason(error); if (reason) { - if (reason === "T-OAEX-01") { - this.removeOrderFromMap(order); - } this.logger.warn( `${this.instanceName} Order Cancel error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( this.baseDisplayDecimals )} @ ${order.price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` ); + if (reason === "T-OAEX-01") { + this.removeOrderFromMap(order); + } } else { this.logger.error( `${this.instanceName} Order Cancel error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( @@ -1281,13 +1267,12 @@ abstract class AbstractBot { } } - async cancelReplaceOrder(order: any, quantity: BigNumber, price: BigNumber) { + async cancelReplaceOrder(order: any, price: BigNumber, quantity: BigNumber) { if (!this.status) { return; } try { - this.checkWashTrade(order.side, price); const priceToSend = utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals); @@ -1295,18 +1280,24 @@ abstract class AbstractBot { quantity.toFixed(this.baseDisplayDecimals), this.contracts[this.base].tokenDetails.evmdecimals ); - const clientOrderId = await this.getClientOrderId(); + + const clientOrderId = await this.getClientOrderId(0,order.level); // Not using the gasEstimate because it fails with P-AFNE1 when funds are tight but the actual C/R doesn't - // const gasest= await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); + console.log("CANCEL REPLACE: Orderid to replace:",order.id, " New clientOrderid: ", clientOrderId," PRICE:", price.toNumber(), " QTY: ", quantity.toNumber()); + + const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); + + console.log("CANCEL REPLACE: GOT GASEST"); + // this.logger.debug (`${this.instanceName} CancelReplace order gasEstimate: ${gasest} `); // ${tcost} this.orderCount++; this.logger.debug( `${this.instanceName} Cancel/Replace OrderNbr: ${this.orderCount} ${ order.side === 0 ? "BUY" : "SELL" - } ::: ${order.quantity.toString()} ${this.base} @ ${order.price.toString()} ${this.quote}` + } ::: ${quantity.toString()} ${this.base} @ ${price.toString()} ${this.quote}` ); - const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); + const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); const tx = await this.tradePair.cancelReplaceOrder(order.id, clientOrderId, priceToSend, quantityToSend, options); const orderLog = await tx.wait(); @@ -1344,27 +1335,26 @@ abstract class AbstractBot { const idx = error.message.indexOf(nonceErr); if (error.code === "NONCE_EXPIRED" || idx > -1) { this.logger.warn( - `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( + `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( this.baseDisplayDecimals - )} @ ${order.price.toFixed(this.quoteDisplayDecimals)} Invalid Nonce` + )} @ ${price.toFixed(this.quoteDisplayDecimals)} Invalid Nonce` ); await this.correctNonce(this.contracts["SubNetProvider"]); } else { const reason = await this.getRevertReason(error); if (reason) { - if (reason === "T-OAEX-01") { - this.removeOrderFromMap(order); - } + console.log("ERR", error); this.logger.warn( - `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( + `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( this.baseDisplayDecimals - )} @ ${order.price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` + )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` ); } else { + console.log("ERR2: ", error); this.logger.error( - `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( + `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( this.baseDisplayDecimals - )} @ ${order.price.toFixed(this.quoteDisplayDecimals)}`, + )} @ ${price.toFixed(this.quoteDisplayDecimals)}`, error ); } @@ -1833,18 +1823,18 @@ abstract class AbstractBot { async checkWashTrade(side: number, price: BigNumber) { if (this.washTradeCheck) { if (side === 0){ - const myBestbid = this.orderbook.bestbid(); - if (myBestbid) { - const order = this.orders.get(myBestbid.orders[0].clientOrderId); - if (order && price.lte(order.price)) { - this.logger.warn( - `${this.instanceName} 'Wash trade not allowed. New SELL order price ${price.toFixed( - this.quoteDisplayDecimals - )} <= Best Bid ${order.price.toString()}` - ); - return; + const myBestask = this.orderbook.bestask(); + if (myBestask) { + const orderBAsk = this.orders.get(myBestask.orders[0].clientOrderId); + if (orderBAsk && price.gte(orderBAsk.price)) { + this.logger.warn( + `${this.instanceName} 'Wash trade in C/R not allowed. New BUY order price ${price.toFixed( + this.quoteDisplayDecimals + )} >= Best Ask ${orderBAsk.price.toString()}` + ); + return; + } } - } } else if (side === 1){ const myBestbid = this.orderbook.bestbid(); if (myBestbid) { @@ -1867,8 +1857,8 @@ abstract class AbstractBot { if (!this.cleanupCalled) { this.logger.warn(`${this.instanceName} === Process Exit Called === `); this.cleanupCalled = true; - this.stop(); - const timeout = Math.max(7, this.getSettingValue("CLEAR_TIMOUT_SECONDS") || 10); //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds + await this.stop(); + const timeout = 10; //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds setTimeout(() => { this.logger.warn(`${this.instanceName} === SHUTTING DOWN === `); process.exit(0); diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index 6c5dfaa..d352632 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -1,9 +1,5 @@ - - - -import SampleBot from "./SampleBot"; import avax_usdc from "./avax_usdc"; -const Bot:any = { SampleBot, avax_usdc}; +const Bot:any = {avax_usdc}; module.exports = { createBot(type:any, attributes:any) { diff --git a/services/bots/SampleBot.ts b/services/bots/SampleBot.ts deleted file mode 100644 index bd9dae3..0000000 --- a/services/bots/SampleBot.ts +++ /dev/null @@ -1,186 +0,0 @@ -import utils from "../utils"; -import BigNumber from "bignumber.js"; -import AbstractBot from "./AbstractBot"; - -class SampleBot extends AbstractBot { - protected marketPrice = new BigNumber(17); //AVAX/USDC - protected baseUsd = 17; //AVAX - protected quoteUsd = 1; //USDC - protected capitalASideUSD = 300; - - constructor(botId: number, pairStr: string, privateKey: string) { - super(botId, pairStr, privateKey); - // Will try to rebalance the amounts in the Portfolio Contract - this.portfolioRebalanceAtStart = true; - } - - async saveBalancestoDb(balancesRefreshed: boolean): Promise { - this.logger.info(`${this.instanceName} Save Balances somewhere if needed`); - } - - async initialize(): Promise { - const initializing = await super.initialize(); - if (initializing) { - await this.getNewMarketPrice(); - - this.interval = 10000; //Min 10 seconds - - this.minTradeAmnt = this.pairObject.mintrade_amnt * 1.1; - this.maxTradeAmnt = this.pairObject.mintrade_amnt * 5; - - // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc - //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); - - return true; - } else { - return false; - } - } - - async startOrderUpdater() { - if (this.status) { - // Enable the next line if you need the bot to run continuously - // this.orderUpdater = setTimeout( () => this.updateOrders(), this.interval ); - // Comment out if you need the bot to run continuously - this.updateOrders(); - } else { - this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); - } - } - - async updateOrders() { - if (this.orderUpdater != undefined) { - clearTimeout(this.orderUpdater); - } - - try { - // Sleep 30 seconds initially for the original funding to reach the subnet. If it takes longer, - // you'll get not enough funds error when sending orders. Ignore the errors and Just restart the bot. - // after making sure that the funds reached the subnet - // await utils.sleep(30000); - - //Bot automatically recovers any active orders from DB - //This displays my local orderbook consisting of my own orders only. NOT from the exchange - //Use this.getBookfromChain() for the Exchange orderbook - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - //const bookinChain = await this.getBookfromChain(); - - //Get rid of any order that is outstanding on this account if needed. - //if you have more than 10-15 outstanding orders on this pair, this function may run out of gas - // use this.cancelAllIndividually() instead. - await this.cancelOrderList([], 100); - - // Sleep 30 seconds initially - await utils.sleep(3000); - - const nbrofOrders = 4; - const halfofOrders = nbrofOrders / 2; - const quantity = new BigNumber(4); - - console.log(this.instanceName, "Sending Buy", nbrofOrders, "orders at different prices"); - let i; - for (i = 0; i < halfofOrders; i++) { - await this.addOrder(utils.sideMap.BUY, quantity, new BigNumber(i / 100 + 16)); - } - console.log(this.instanceName, "Sending Sell", nbrofOrders, "orders at different prices"); - for (i = 0; i < halfofOrders; i++) { - await this.addOrder(utils.sideMap.SELL, quantity, new BigNumber(i / 100 + 17)); - } - console.log(this.instanceName, "Sleeping 10 seconds"); - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - await utils.sleep(10000); - - console.log(this.instanceName, "Cancelling all outstanding orders individually"); - await this.cancelAllIndividually(); - await utils.sleep(3000); - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - - console.log(this.instanceName, "Attempting to Sending and then fill from the same wallet address", nbrofOrders, "orders"); - for (i = 0; i < nbrofOrders; i++) { - await this.addOrder(utils.sideMap.BUY, quantity, new BigNumber(i / 100 + 17)); - } - - //AbstractBot implementation will not allow wash trade. So the following orders won't be sent out. - for (i = 0; i < nbrofOrders; i++) { - await this.addOrder(utils.sideMap.SELL, quantity, new BigNumber(i / 100 + 17)); - } - - await utils.sleep(3000); - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - - //Market Orders need to be enabled for the pair. Otherwise these orders will revert.. - //See error.json in the root for the explanation of the revert reason codes. - //The latest revert reasons are available at https://api.dexalot-test.com/api/trading/errorcodes - for (i = 0; i < nbrofOrders; i++) { - await this.addOrder(utils.sideMap.SELL, quantity, undefined, 0); // Send Market Orders - } - - await utils.sleep(1000); - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - process.exit(0); - } catch (error) { - this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); - process.exit(1); - } finally { - // Enable the next line if you need the bot to run continuously - // this.startOrderUpdater(); - } - } - - getQuantity(price: BigNumber, side: number) { - return new BigNumber(this.minTradeAmnt).div(price); - } - - getPrice(side: number): BigNumber { - return this.marketPrice; - } - - // Update the marketPrice from an outside source - async getNewMarketPrice() { - try { - // TODO Implement your own price source to get the Base & Quote price from an external source if necessary - - // this.setMarketPrice(PriceService.prices[this.priceSymbolPair.pair]); - // this.baseUsd = PriceService.prices[this.priceSymbolPair.base]; - // this.quoteUsd = PriceService.prices[this.priceSymbolPair.quote]; - - this.baseUsd = 17; //AVAX - this.quoteUsd = 1; //USDC - } catch (error: any) { - this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); - } - return this.marketPrice; - } - - setMarketPrice(price: number) { - this.marketPrice = new BigNumber(price); - } - - async getAlotPrice(): Promise { - let alotprice = 0.25; - try { - alotprice = 0.25; // FIXME Implement your own price source to get the ALOT price - } catch (error) { - this.logger.error(`${this.instanceName} Error during getAlotPrice`, error); - } - return alotprice; - } - - getBaseCapital(): number { - if (this.baseUsd) { - return parseFloat((this.capitalASideUSD / this.baseUsd).toFixed(this.baseDisplayDecimals)); - } else { - return this.initialDepositBase; - } - } - - getQuoteCapital(): number { - if (this.quoteUsd) { - return parseFloat((this.capitalASideUSD / this.quoteUsd).toFixed(this.quoteDisplayDecimals)); - } else { - return this.initialDepositQuote; - } - } -} - -export default SampleBot; diff --git a/services/bots/avax_usdc.ts b/services/bots/avax_usdc.ts index 98a4101..c8475bd 100644 --- a/services/bots/avax_usdc.ts +++ b/services/bots/avax_usdc.ts @@ -3,7 +3,9 @@ import utils from "../utils"; import BigNumber from "bignumber.js"; import AbstractBot from "./AbstractBot"; import NewOrder from "./classes"; +import Order from "../../models/order"; import { error } from "console"; +import { BrotliDecompress } from "zlib"; class avax_usdc extends AbstractBot { protected marketPrice = new BigNumber(17); //AVAX/USDC @@ -19,7 +21,7 @@ class avax_usdc extends AbstractBot { this.bidSpread = 0.3; this.askSpread = 0.3; this.orderLevels = 2; - this.orderLevelSpread = 0.05; + this.orderLevelSpread = 0.1; this.orderLevelQty = BigNumber(10); } @@ -62,11 +64,19 @@ class avax_usdc extends AbstractBot { await this.cancelOrderList([], 100); // ------------ Create and Send Initial Order List ------------ // - await this.placeInitialOrders() + let levels : number[][] = []; + for (let i = 1; i <= this.orderLevels; i++){ + levels.push([0,i]); + levels.push([1,i]); + } + + await this.placeInitialOrders(levels); // ------------ Begin Order Updater ------------ // - this.updateOrders(); + this.orderUpdater = setTimeout(()=>{ + this.updateOrders(); + }, this.interval); } else { this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); @@ -83,110 +93,138 @@ class avax_usdc extends AbstractBot { console.log("000000000000000 COUNTER:",this.counter); const marketPrice = this.getPrice(1).toNumber(); - const initialBidPrice = marketPrice * (1-this.bidSpread/100); - const initialAskPrice = marketPrice * (1+this.askSpread/100); + const startingBidPrice = marketPrice * (1-this.bidSpread/100); + const startingAskPrice = marketPrice * (1+this.askSpread/100); - let bids = sortOrders(this.orderbook.state().bids, "price", "descending"); - let asks = sortOrders(this.orderbook.state().asks, "price", "ascending"); - let baseEnRoute = 0; - let quoteEnRoute = 0; + let bids: object[] = []; + let asks: object[] = []; - if (bids.length < this.orderLevels){ - this.placeInitialOrders(true,false); - } else { - bids.forEach((e: any,i: number) => { - let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.base].portfolioTot + (e.quantity * bidPrice.toNumber()) - quoteEnRoute)); - if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - quoteEnRoute += bidQty.toNumber(); - this.cancelReplaceOrder(e,bidPrice,bidQty); - } else { - return; - } - }) - } + this.orders.forEach((e,i)=>{ + if (e.side === 0){ + bids.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); + } else { + asks.push({side:e.side,id:e.id,price:e.price.toNumber()}); + } + }) + + let bidsSorted = sortOrders(bids, "price", "descending"); + let asksSorted = sortOrders(asks, "price", "ascending"); + + // await this.cancelOrderList([], 100); + + // ------------ Create and Send Initial Order List ------------ // + + console.log("BIDS SORTED:",bidsSorted,"this.orderLevels:",this.orderLevels); - if (asks.length < this.orderLevels){ - this.placeInitialOrders(false,true); + if (bidsSorted.length < this.orderLevels){ + //this.placeInitialOrders(true,false); } else { - asks.forEach((e: any,i: number) => { - let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); - let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.quote].portfolioTot + e.quantity - baseEnRoute)); - if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - baseEnRoute += askQty.toNumber(); - this.cancelReplaceOrder(e,askPrice,askQty); + console.log("REPLACE BIDS: ",bidsSorted.length); + let bidsEnRoute = 0; + + for (let i = 0; i < this.orderLevels; i ++){ + let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; + for (let j = 0; j < bidsSorted.length; j++){ + if (bidsSorted[j].level == i+1){ + order = bidsSorted[j]; + console.log("ORDER: ", order); + } } - }) + if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ + let bidPrice = new BigNumber(0.99 * startingBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); + console.log("REPLACE ORDER:",bidPrice,bidQty); + this.cancelReplaceOrder(order,bidPrice,bidQty); + } else { + console.log("NOT ENOUGH FUNDS TO REPLACE", bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); + } + } else { + console.log("MAKE FRESH ORDER"); + this.placeInitialOrders([[0,i]]); + } + } } - - - this.logger.debug(`orderbook:${JSON.stringify(this.getOrderBook())}`); + // if (asksSorted.length < this.orderLevels){ + // this.placeInitialOrders(false,true); + // } else { + // let asksEnRoute = 0; + // asksSorted.forEach(async (e: any,i: number) => { + // e.level = i + 100; //for getClientOrderId if multiple orders are created simultaneously + // let askPrice = new BigNumber(startingAskPrice * (1+(i*this.orderLevelSpread/100))); + // let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.base].portfolioTot + e.quantity - asksEnRoute)); + // if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + // asksEnRoute += askQty.toNumber(); + // await this.cancelReplaceOrder(e,askPrice,askQty); + // } + // }) + // } } catch (error) { this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); - process.exit(1); + this.cleanUpAndExit(); } finally { - - // Wait before updating orders again - await utils.sleep(this.interval); - await this.cancelOrderList([], 100); - //Update Orders Again - this.updateOrders(); + //Update orders again after interval + this.orderUpdater = setTimeout(()=>{ + this.cleanUpAndExit(); + // this.updateOrders(); + }, this.interval); } } - async placeInitialOrders(setBids: boolean = true, setAsks: boolean = true){ + // Takes in an array of arrays. The first number of each subarray is the side, the second is the level. + // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList + async placeInitialOrders(levels: number[][]){ + const marketPrice = this.getPrice(1).toNumber(); const initialBidPrice = marketPrice * (1-this.bidSpread/100); const initialAskPrice = marketPrice * (1+this.askSpread/100); let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // - if (setBids){ - let bidsEnroute = 0; - for (let i = 0; i < this.orderLevels; i++) { - let bidPrice = new BigNumber(initialBidPrice * (1-(i*this.orderLevelSpread/100))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i,this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); + let bidsEnroute = 0; + let asksEnRoute = 0; + for (let x = 0; x < levels.length; x++){ + if (levels[x][0] == 0){ + let bidPrice = new BigNumber(initialBidPrice * (1-(levels[x][1]*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ bidsEnroute += bidQty.toNumber(); - console.log("BID LEVEL ",i,": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); - newOrderList.push(new NewOrder(0,bidQty,bidPrice)); + console.log("BID LEVEL ",levels[x][0],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); + newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } + } else { + //--------------- SET ASKS --------------- // + // let askPrice = new BigNumber(initialAskPrice * (1+(levels[x][1]*this.orderLevelSpread/100))); + // let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioTot - asksEnRoute)); + // console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); + // if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + // asksEnRoute += askQty.toNumber(); + // newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); + // } } } - // --------------- SET ASKS --------------- // - if (setAsks){ - let asksEnRoute = 0; - for (let i = 0; i < this.orderLevels; i++) { - let askPrice = new BigNumber(initialAskPrice * (1+(i*this.orderLevelSpread/100))); - let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.base].portfolioTot - asksEnRoute)); - console.log("ASK LEVEL ",i,": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); - if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - asksEnRoute += askQty.toNumber(); - newOrderList.push(new NewOrder(1,askQty,askPrice)); - } - } - } - - console.log("NEW ORDER LIST:",newOrderList); - // --------------- EXECUTE ORDERS --------------- // + // // --------------- EXECUTE ORDERS --------------- // await this.addLimitOrderList(newOrderList); } + // Takes in price, side, level, and availableFunds. Returns amount to place. + // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ - console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",(level+1) * this.orderLevelQty.toNumber()) - if ((level+1) * this.orderLevelQty.toNumber() < availableFunds){ - return (level+1) * this.orderLevelQty.toNumber(); + console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",(level) * this.orderLevelQty.toNumber()) + if ((level) * this.orderLevelQty.toNumber() < availableFunds){ + return (level) * this.orderLevelQty.toNumber(); } else if (availableFunds > this.minTradeAmnt * 1.1){ return availableFunds*.9; } else { return 0;} } else if (side === 1) { - console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",(level+1) * this.orderLevelQty.toNumber()) - if ((level+1) * this.orderLevelQty.toNumber() < availableFunds){ - return (level+1) * this.orderLevelQty.toNumber(); + console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",(level) * this.orderLevelQty.toNumber()) + if ((level) * this.orderLevelQty.toNumber() < availableFunds){ + return (level) * this.orderLevelQty.toNumber(); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 1.1){ return availableFunds * .9; } else {return 0;} diff --git a/services/bots/classes.ts b/services/bots/classes.ts index 5dcd0ae..fb5ca39 100644 --- a/services/bots/classes.ts +++ b/services/bots/classes.ts @@ -4,10 +4,12 @@ class NewOrder { public side: number; public quantity: BigNumber; public price: BigNumber; - constructor(side: number, quantity: BigNumber, price: BigNumber) { + public level: number; + constructor(side: number, quantity: BigNumber, price: BigNumber, level: number) { this.side = side; this.quantity = quantity; this.price = price; + this.level = level; } } From 03af3a0ec894620320636ea608c9b1d5e2d047c8 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Thu, 13 Jul 2023 14:45:40 +0700 Subject: [PATCH 010/173] bids and asks working. Can place and replace 10 orders at a time --- services/bots/AbstractBot.ts | 18 ++-- services/bots/avax_usdc.ts | 174 ++++++++++++++++++++--------------- 2 files changed, 111 insertions(+), 81 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index ded1619..70bb045 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1280,24 +1280,28 @@ abstract class AbstractBot { quantity.toFixed(this.baseDisplayDecimals), this.contracts[this.base].tokenDetails.evmdecimals ); - - const clientOrderId = await this.getClientOrderId(0,order.level); + //get unique counter to generate clientOrderId + let counter = order.level; + if (order.side == 1){ + counter = counter + 100; + } + const clientOrderId = await this.getClientOrderId(0,counter); // Not using the gasEstimate because it fails with P-AFNE1 when funds are tight but the actual C/R doesn't console.log("CANCEL REPLACE: Orderid to replace:",order.id, " New clientOrderid: ", clientOrderId," PRICE:", price.toNumber(), " QTY: ", quantity.toNumber()); - const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); + //const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); - console.log("CANCEL REPLACE: GOT GASEST"); + //console.log("CANCEL REPLACE: GOT GASEST"); - // this.logger.debug (`${this.instanceName} CancelReplace order gasEstimate: ${gasest} `); // ${tcost} + //this.logger.debug (`${this.instanceName} CancelReplace order gasEstimate: ${gasest} `); // ${tcost} this.orderCount++; this.logger.debug( `${this.instanceName} Cancel/Replace OrderNbr: ${this.orderCount} ${ order.side === 0 ? "BUY" : "SELL" } ::: ${quantity.toString()} ${this.base} @ ${price.toString()} ${this.quote}` ); - const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); + const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); const tx = await this.tradePair.cancelReplaceOrder(order.id, clientOrderId, priceToSend, quantityToSend, options); const orderLog = await tx.wait(); @@ -1343,14 +1347,12 @@ abstract class AbstractBot { } else { const reason = await this.getRevertReason(error); if (reason) { - console.log("ERR", error); this.logger.warn( `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( this.baseDisplayDecimals )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` ); } else { - console.log("ERR2: ", error); this.logger.error( `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( this.baseDisplayDecimals diff --git a/services/bots/avax_usdc.ts b/services/bots/avax_usdc.ts index c8475bd..f027552 100644 --- a/services/bots/avax_usdc.ts +++ b/services/bots/avax_usdc.ts @@ -22,7 +22,7 @@ class avax_usdc extends AbstractBot { this.askSpread = 0.3; this.orderLevels = 2; this.orderLevelSpread = 0.1; - this.orderLevelQty = BigNumber(10); + this.orderLevelQty = BigNumber(2); } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -34,7 +34,7 @@ class avax_usdc extends AbstractBot { if (initializing) { await this.getNewMarketPrice(); - this.interval = 10000; //Min 10 seconds + this.interval = 15000; //Min 10 seconds // this.minTradeAmnt = this.pairObject.mintrade_amnt * 1.1; // this.maxTradeAmnt = this.pairObject.mintrade_amnt * 5; @@ -76,7 +76,7 @@ class avax_usdc extends AbstractBot { this.orderUpdater = setTimeout(()=>{ this.updateOrders(); - }, this.interval); + }, this.interval/2); } else { this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); @@ -104,72 +104,24 @@ class avax_usdc extends AbstractBot { if (e.side === 0){ bids.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); } else { - asks.push({side:e.side,id:e.id,price:e.price.toNumber()}); + asks.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); } }) let bidsSorted = sortOrders(bids, "price", "descending"); let asksSorted = sortOrders(asks, "price", "ascending"); - // await this.cancelOrderList([], 100); - - // ------------ Create and Send Initial Order List ------------ // - - console.log("BIDS SORTED:",bidsSorted,"this.orderLevels:",this.orderLevels); - - if (bidsSorted.length < this.orderLevels){ - //this.placeInitialOrders(true,false); - } else { - console.log("REPLACE BIDS: ",bidsSorted.length); - let bidsEnRoute = 0; - - for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; - for (let j = 0; j < bidsSorted.length; j++){ - if (bidsSorted[j].level == i+1){ - order = bidsSorted[j]; - console.log("ORDER: ", order); - } - } - if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let bidPrice = new BigNumber(0.99 * startingBidPrice * (1-(i*this.orderLevelSpread/100))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); - if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); - console.log("REPLACE ORDER:",bidPrice,bidQty); - this.cancelReplaceOrder(order,bidPrice,bidQty); - } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); - } - } else { - console.log("MAKE FRESH ORDER"); - this.placeInitialOrders([[0,i]]); - } - } - } + this.replaceBids(bidsSorted, startingBidPrice); + this.replaceAsks(asksSorted, startingAskPrice); - // if (asksSorted.length < this.orderLevels){ - // this.placeInitialOrders(false,true); - // } else { - // let asksEnRoute = 0; - // asksSorted.forEach(async (e: any,i: number) => { - // e.level = i + 100; //for getClientOrderId if multiple orders are created simultaneously - // let askPrice = new BigNumber(startingAskPrice * (1+(i*this.orderLevelSpread/100))); - // let askQty = new BigNumber(this.getQty(askPrice,1,i,this.contracts[this.base].portfolioTot + e.quantity - asksEnRoute)); - // if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - // asksEnRoute += askQty.toNumber(); - // await this.cancelReplaceOrder(e,askPrice,askQty); - // } - // }) - // } - } catch (error) { this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); this.cleanUpAndExit(); } finally { //Update orders again after interval - this.orderUpdater = setTimeout(()=>{ + this.orderUpdater = setTimeout(async ()=>{ this.cleanUpAndExit(); + // await this.getNewMarketPrice(); // this.updateOrders(); }, this.interval); } @@ -191,19 +143,19 @@ class avax_usdc extends AbstractBot { let bidPrice = new BigNumber(initialBidPrice * (1-(levels[x][1]*this.orderLevelSpread/100))); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - bidsEnroute += bidQty.toNumber(); console.log("BID LEVEL ",levels[x][0],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); + bidsEnroute += bidQty.toNumber(); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } } else { //--------------- SET ASKS --------------- // - // let askPrice = new BigNumber(initialAskPrice * (1+(levels[x][1]*this.orderLevelSpread/100))); - // let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioTot - asksEnRoute)); - // console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); - // if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - // asksEnRoute += askQty.toNumber(); - // newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); - // } + let askPrice = new BigNumber(initialAskPrice * (1+(levels[x][1]*this.orderLevelSpread/100))); + let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioTot - asksEnRoute)); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); + asksEnRoute += askQty.toNumber(); + newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); + } } } @@ -211,6 +163,73 @@ class avax_usdc extends AbstractBot { await this.addLimitOrderList(newOrderList); } + async replaceBids(bidsSorted: any, startingBidPrice: number){ + console.log("REPLACE BIDS: ",bidsSorted.length); + let bidsEnRoute = 0; + let timer = 0; + for (let i = 0; i < this.orderLevels; i ++){ + let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; + for (let j = 0; j < bidsSorted.length; j++){ + if (bidsSorted[j].level == i+1){ + order = bidsSorted[j]; + console.log("BID ORDER: ", order); + } + } + // We need a timer because you cannot replace or make multiple individual orders on the same pair on the same side in one block + setTimeout(()=>{ + timer += 3000; + if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ + let bidPrice = new BigNumber(0.99 * startingBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); + console.log("REPLACE ORDER:",bidPrice,bidQty); + this.cancelReplaceOrder(order,bidPrice,bidQty); + } else { + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); + } + } else { + console.log("MAKE FRESH ORDER"); + this.placeInitialOrders([[0,i+1]]); + } + },0); + } + } + + async replaceAsks (asksSorted: any, startingAskPrice: number){ + console.log("REPLACE ASKS: ",asksSorted.length); + let asksEnRoute = 0; + let timer = 0; + + for (let i = 0; i < this.orderLevels; i ++){ + let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; + for (let j = 0; j < asksSorted.length; j++){ + if (asksSorted[j].level == i+1){ + order = asksSorted[j]; + console.log("ASK ORDER: ", order); + } + } + // We need a timer because you cannot replace or make multiple individual orders on the same pair on the same side in one block + setTimeout(()=>{ + timer += 3000; + if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ + let askPrice = new BigNumber(1.01 * startingAskPrice * (1-(i*this.orderLevelSpread/100))); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioTot + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); + console.log("REPLACE ORDER:",askPrice,askQty); + this.cancelReplaceOrder(order,askPrice,askQty); + } else { + console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); + } + } else { + console.log("MAKE FRESH ORDER"); + this.placeInitialOrders([[1,i+1]]); + } + },0); + } + } + // Takes in price, side, level, and availableFunds. Returns amount to place. // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { @@ -218,17 +237,19 @@ class avax_usdc extends AbstractBot { console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",(level) * this.orderLevelQty.toNumber()) if ((level) * this.orderLevelQty.toNumber() < availableFunds){ return (level) * this.orderLevelQty.toNumber(); - } else if (availableFunds > this.minTradeAmnt * 1.1){ - return availableFunds*.9; + } else if (availableFunds > this.minTradeAmnt * 1.025){ + return availableFunds*.975; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",(level) * this.orderLevelQty.toNumber()) if ((level) * this.orderLevelQty.toNumber() < availableFunds){ return (level) * this.orderLevelQty.toNumber(); - } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 1.1){ - return availableFunds * .9; + } else if (availableFunds > this.minTradeAmnt * 1.025){ + return availableFunds * .975; } else {return 0;} - } else { return 0;} + } else { + return 0; // function declaration requires I return a number + } } getPrice(side: number): BigNumber { @@ -238,11 +259,18 @@ class avax_usdc extends AbstractBot { // Update the marketPrice from an outside source async getNewMarketPrice() { try { - // let response_avax = await axios.get('http://localhost/avax_usd'); - this.baseUsd = 12; //response_avax.data; //AVAX + let response_base = await axios.get('http://localhost/'+this.base); + this.baseUsd = response_base.data; //AVAX - // let response_usdc = await axios.get('http://localhost/usdc_usd'); - this.quoteUsd = 1; //response_usdc.data; //USDC + let response_quote = await axios.get('http://localhost/'+this.quote); + this.quoteUsd = response_quote.data; //USDC + + if (!this.baseUsd){ + this.baseUsd = 12; + } + if (!this.quoteUsd){ + this.quoteUsd = 1; + } this.setMarketPrice(this.baseUsd/this.quoteUsd); } catch (error: any) { From d287d1c33c41c718fa7fff261ec88e1c64e92344 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Thu, 13 Jul 2023 14:57:22 +0700 Subject: [PATCH 011/173] rename bot to Market Maker Bot. Removed unnecessary timers. adjusted getNewMarketPrice to handle other pairs --- services/bots/BotFactory.ts | 4 +- .../bots/{avax_usdc.ts => MarketMakerBot.ts} | 78 +++++++++---------- 2 files changed, 38 insertions(+), 44 deletions(-) rename services/bots/{avax_usdc.ts => MarketMakerBot.ts} (76%) diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index d352632..9a1b0ac 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -1,5 +1,5 @@ -import avax_usdc from "./avax_usdc"; -const Bot:any = {avax_usdc}; +import MarketMakerBot from "./MarketMakerBot"; +const Bot:any = {MarketMakerBot}; module.exports = { createBot(type:any, attributes:any) { diff --git a/services/bots/avax_usdc.ts b/services/bots/MarketMakerBot.ts similarity index 76% rename from services/bots/avax_usdc.ts rename to services/bots/MarketMakerBot.ts index f027552..72a5256 100644 --- a/services/bots/avax_usdc.ts +++ b/services/bots/MarketMakerBot.ts @@ -7,10 +7,10 @@ import Order from "../../models/order"; import { error } from "console"; import { BrotliDecompress } from "zlib"; -class avax_usdc extends AbstractBot { - protected marketPrice = new BigNumber(17); //AVAX/USDC - protected baseUsd = 13; //AVAX - protected quoteUsd = 1; //USDC +class MarketMakerBot extends AbstractBot { + protected marketPrice = new BigNumber(17); + protected baseUsd = 13; + protected quoteUsd = 1; protected capitalASideUSD = 300; protected counter = 0; @@ -146,6 +146,8 @@ class avax_usdc extends AbstractBot { console.log("BID LEVEL ",levels[x][0],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); bidsEnroute += bidQty.toNumber(); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); + } else { + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL BID: ", levels[x][1];) } } else { //--------------- SET ASKS --------------- // @@ -155,6 +157,8 @@ class avax_usdc extends AbstractBot { console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); asksEnRoute += askQty.toNumber(); newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); + } else { + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK: ", levels[x][1];) } } } @@ -166,7 +170,6 @@ class avax_usdc extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); let bidsEnRoute = 0; - let timer = 0; for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; for (let j = 0; j < bidsSorted.length; j++){ @@ -175,31 +178,26 @@ class avax_usdc extends AbstractBot { console.log("BID ORDER: ", order); } } - // We need a timer because you cannot replace or make multiple individual orders on the same pair on the same side in one block - setTimeout(()=>{ - timer += 3000; - if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let bidPrice = new BigNumber(0.99 * startingBidPrice * (1-(i*this.orderLevelSpread/100))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); - if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); - console.log("REPLACE ORDER:",bidPrice,bidQty); - this.cancelReplaceOrder(order,bidPrice,bidQty); - } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); - } + if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ + let bidPrice = new BigNumber(0.99 * startingBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); + console.log("REPLACE ORDER:",bidPrice,bidQty); + this.cancelReplaceOrder(order,bidPrice,bidQty); } else { - console.log("MAKE FRESH ORDER"); - this.placeInitialOrders([[0,i+1]]); + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); } - },0); + } else { + console.log("MAKE FRESH ORDER"); + this.placeInitialOrders([[0,i+1]]); + } } } async replaceAsks (asksSorted: any, startingAskPrice: number){ console.log("REPLACE ASKS: ",asksSorted.length); let asksEnRoute = 0; - let timer = 0; for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; @@ -209,24 +207,20 @@ class avax_usdc extends AbstractBot { console.log("ASK ORDER: ", order); } } - // We need a timer because you cannot replace or make multiple individual orders on the same pair on the same side in one block - setTimeout(()=>{ - timer += 3000; - if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let askPrice = new BigNumber(1.01 * startingAskPrice * (1-(i*this.orderLevelSpread/100))); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioTot + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); - if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); - console.log("REPLACE ORDER:",askPrice,askQty); - this.cancelReplaceOrder(order,askPrice,askQty); - } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); - } + if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ + let askPrice = new BigNumber(1.01 * startingAskPrice * (1-(i*this.orderLevelSpread/100))); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioTot + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); + console.log("REPLACE ORDER:",askPrice,askQty); + this.cancelReplaceOrder(order,askPrice,askQty); } else { - console.log("MAKE FRESH ORDER"); - this.placeInitialOrders([[1,i+1]]); + console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); } - },0); + } else { + console.log("MAKE FRESH ORDER"); + this.placeInitialOrders([[1,i+1]]); + } } } @@ -260,15 +254,15 @@ class avax_usdc extends AbstractBot { async getNewMarketPrice() { try { let response_base = await axios.get('http://localhost/'+this.base); - this.baseUsd = response_base.data; //AVAX + this.baseUsd = response_base.data; let response_quote = await axios.get('http://localhost/'+this.quote); - this.quoteUsd = response_quote.data; //USDC + this.quoteUsd = response_quote.data; - if (!this.baseUsd){ + if (!this.baseUsd){ //AVAX for testing this.baseUsd = 12; } - if (!this.quoteUsd){ + if (!this.quoteUsd){ //USDC for testing this.quoteUsd = 1; } From 7173cb364ec9ddc54367647a60b53c4295d22d2c Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Thu, 13 Jul 2023 15:26:15 +0700 Subject: [PATCH 012/173] removed hardcoded % adjustments for replacement order testing --- package.json | 2 +- services/bots/MarketMakerBot.ts | 31 ++++++++++++------------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index ba53c17..4aa7829 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "sampleBot-hh": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=local-hh --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "sampleBot-dev": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=development --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "sampleBot-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "avax_usdc-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", + "marketMakerBot-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "loadBot": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "loadBot1": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp@1 --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", "loadBot2": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp@2 --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 72a5256..9fae60f 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -91,10 +91,8 @@ class MarketMakerBot extends AbstractBot { try { this.counter ++; console.log("000000000000000 COUNTER:",this.counter); - - const marketPrice = this.getPrice(1).toNumber(); - const startingBidPrice = marketPrice * (1-this.bidSpread/100); - const startingAskPrice = marketPrice * (1+this.askSpread/100); + const startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); + const startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); let bids: object[] = []; @@ -131,9 +129,8 @@ class MarketMakerBot extends AbstractBot { // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList async placeInitialOrders(levels: number[][]){ - const marketPrice = this.getPrice(1).toNumber(); - const initialBidPrice = marketPrice * (1-this.bidSpread/100); - const initialAskPrice = marketPrice * (1+this.askSpread/100); + const initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); + const initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // let bidsEnroute = 0; @@ -147,7 +144,7 @@ class MarketMakerBot extends AbstractBot { bidsEnroute += bidQty.toNumber(); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } else { - console.log("NOT ENOUGH FUNDS TO PLACE INITIAL BID: ", levels[x][1];) + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL BID: ", levels[x][1]) } } else { //--------------- SET ASKS --------------- // @@ -158,7 +155,7 @@ class MarketMakerBot extends AbstractBot { asksEnRoute += askQty.toNumber(); newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); } else { - console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK: ", levels[x][1];) + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK: ", levels[x][1]) } } } @@ -179,7 +176,7 @@ class MarketMakerBot extends AbstractBot { } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let bidPrice = new BigNumber(0.99 * startingBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidPrice = new BigNumber(startingBidPrice * (1-(i*this.orderLevelSpread/100))); let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); @@ -208,7 +205,7 @@ class MarketMakerBot extends AbstractBot { } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let askPrice = new BigNumber(1.01 * startingAskPrice * (1-(i*this.orderLevelSpread/100))); + let askPrice = new BigNumber(startingAskPrice * (1-(i*this.orderLevelSpread/100))); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioTot + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); @@ -246,10 +243,6 @@ class MarketMakerBot extends AbstractBot { } } - getPrice(side: number): BigNumber { - return this.marketPrice; - } - // Update the marketPrice from an outside source async getNewMarketPrice() { try { @@ -266,15 +259,15 @@ class MarketMakerBot extends AbstractBot { this.quoteUsd = 1; } - this.setMarketPrice(this.baseUsd/this.quoteUsd); + this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); } catch (error: any) { this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); } return this.marketPrice; } - setMarketPrice(price: number) { - this.marketPrice = new BigNumber(price); + getPrice(side: number): BigNumber { + return this.marketPrice; } async getAlotPrice(): Promise { @@ -323,4 +316,4 @@ const sortOrders = (arr: any, propertyName: any, order: string = 'ascending') => return sortedArr; }; -export default avax_usdc; +export default MarketMakerBot; From 4e15464cec49328416cba37b9d1336b6fd0b8f76 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Fri, 14 Jul 2023 01:18:03 +0700 Subject: [PATCH 013/173] fixed order level logging/tracking, getqty, getspread, and added configs --- services/bots/AbstractBot.ts | 40 +++++--- services/bots/MarketMakerBot.ts | 172 +++++++++++++++++--------------- services/bots/classes.ts | 1 + 3 files changed, 119 insertions(+), 94 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 70bb045..47db923 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -63,12 +63,6 @@ abstract class AbstractBot { protected signature: any; protected axiosConfig: any; - protected bidSpread: any; - protected askSpread: any; - protected orderLevels: any; - protected orderLevelSpread: any; - protected orderLevelQty: any; - constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { this.logger = getLogger("Bot"); this.instanceName = botId + ":" + pairStr; @@ -415,6 +409,7 @@ abstract class AbstractBot { for (let i = 0; i < newOrders.length; i++){ const clientOrderId = await this.getClientOrderId(blocknumber, i); + newOrders[i].clientOrderId = clientOrderId; const priceToSend = utils.parseUnits( newOrders[i].price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals @@ -477,6 +472,12 @@ abstract class AbstractBot { if (_log.event) { if (_log.event === "OrderStatusChanged") { if (_log.args.traderaddress === this.account && _log.args.pair === this.tradePairByte32) { + let level = 0; + for (let i = 0; i < newOrders.length; i++){ + if (newOrders[i].clientOrderId == _log.args.clientOrderId){ + level = newOrders[i].level; + } + } await this.processOrders( _log.args.version, this.account, @@ -493,7 +494,8 @@ abstract class AbstractBot { _log.args.quantityfilled, _log.args.totalfee, _log.args.code, - _log + _log, + level ); } } @@ -662,7 +664,8 @@ abstract class AbstractBot { _log.args.quantityfilled, _log.args.totalfee, _log.args.code, - _log + _log, + level ); } } @@ -989,7 +992,8 @@ abstract class AbstractBot { quantityfilled: any, totalfee: any, code: any, - event: any + event: any, + level: any ) { try { if (pair === this.tradePairByte32) { @@ -1013,7 +1017,8 @@ abstract class AbstractBot { event.blockNumber, tx.gasUsed.toString(), tx.effectiveGasPrice ? tx.effectiveGasPrice.toString() : "225", - tx.cumulativeGasUsed.toString() + tx.cumulativeGasUsed.toString(), + level ); if (utils.statusMap[order.status] === "NEW" || utils.statusMap[order.status] === "PARTIAL") { @@ -1164,7 +1169,8 @@ abstract class AbstractBot { _log.args.quantityfilled, _log.args.totalfee, _log.args.code, - _log + _log, + -1 ); } } @@ -1225,7 +1231,8 @@ abstract class AbstractBot { _log.args.quantityfilled, _log.args.totalfee, _log.args.code, - _log + _log, + -1 ); } } @@ -1326,7 +1333,8 @@ abstract class AbstractBot { _log.args.quantityfilled, _log.args.totalfee, _log.args.code, - _log + _log, + order.level ); } } @@ -1403,6 +1411,7 @@ abstract class AbstractBot { } await this.checkOrdersInChain(); this.logger.info(`${this.instanceName} open orders recovered:`); + return true; } // Check the satus of the outstanding orders and remove if filled/canceled @@ -1857,10 +1866,13 @@ abstract class AbstractBot { async cleanUpAndExit() { if (!this.cleanupCalled) { + const timeout = 10; //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds this.logger.warn(`${this.instanceName} === Process Exit Called === `); this.cleanupCalled = true; + await utils.sleep(10000); + this.logger.warn(`${this.instanceName} === STOPPING === `); await this.stop(); - const timeout = 10; //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds + setTimeout(() => { this.logger.warn(`${this.instanceName} === SHUTTING DOWN === `); process.exit(0); diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9fae60f..080dd1f 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -1,28 +1,36 @@ import axios from "axios"; +import { getConfig } from "../../config"; import utils from "../utils"; import BigNumber from "bignumber.js"; import AbstractBot from "./AbstractBot"; import NewOrder from "./classes"; -import Order from "../../models/order"; -import { error } from "console"; -import { BrotliDecompress } from "zlib"; class MarketMakerBot extends AbstractBot { - protected marketPrice = new BigNumber(17); - protected baseUsd = 13; - protected quoteUsd = 1; + protected marketPrice = new BigNumber(0); + protected baseUsd = 0; + protected quoteUsd = 0; protected capitalASideUSD = 300; protected counter = 0; + protected lastMarketPrice = new BigNumber(0); + protected bidSpread: any; + protected askSpread: any; + protected orderLevels: any; + protected orderLevelSpread: any; + protected orderLevelQty: any; + protected refreshOrderTolerance: any; + protected flatAmount: any; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); // Will try to rebalance the amounts in the Portfolio Contract this.portfolioRebalanceAtStart = false; - this.bidSpread = 0.3; - this.askSpread = 0.3; - this.orderLevels = 2; - this.orderLevelSpread = 0.1; - this.orderLevelQty = BigNumber(2); + this.bidSpread = getConfig("bidSpread"); + this.askSpread = getConfig("askSpread"); + this.orderLevels = getConfig("orderLevels"); + this.orderLevelSpread = getConfig("orderLevelSpread"); + this.orderLevelQty = getConfig("orderLevelQty"); + this.refreshOrderTolerance = getConfig("refreshOrderTolerance"); + this.flatAmount = getConfig("flatAmount"); } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -36,9 +44,6 @@ class MarketMakerBot extends AbstractBot { this.interval = 15000; //Min 10 seconds - // this.minTradeAmnt = this.pairObject.mintrade_amnt * 1.1; - // this.maxTradeAmnt = this.pairObject.mintrade_amnt * 5; - // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -52,32 +57,36 @@ class MarketMakerBot extends AbstractBot { if (this.status) { // Sleep 30 seconds initially if rebalancing portfolio if (this.portfolioRebalanceAtStart){ - await utils.sleep(3000); + await utils.sleep(30000); } this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - //const bookinChain = await this.getBookfromChain(); - //Get rid of any order that is outstanding on this account if needed. - //if you have more than 10-15 outstanding orders on this pair, this function may run out of gas - // use this.cancelAllIndividually() instead. + //Cancel any remaining orders await this.cancelOrderList([], 100); - // ------------ Create and Send Initial Order List ------------ // - let levels : number[][] = []; - for (let i = 1; i <= this.orderLevels; i++){ - levels.push([0,i]); - levels.push([1,i]); - } - - await this.placeInitialOrders(levels); + if (this.baseUsd && this.quoteUsd){ + // ------------ Create and Send Initial Order List ------------ // + let levels : number[][] = []; + for (let i = 1; i <= this.orderLevels; i++){ + levels.push([0,i]); + levels.push([1,i]); + } - // ------------ Begin Order Updater ------------ // + await this.placeInitialOrders(levels); - this.orderUpdater = setTimeout(()=>{ - this.updateOrders(); - }, this.interval/2); + // ------------ Begin Order Updater ------------ // + this.orderUpdater = setTimeout(()=>{ + this.lastMarketPrice = this.marketPrice; + this.updateOrders(); + }, this.interval/2); + } else { + console.log("MISSING PRICE DATA - baseUsd:",this.baseUsd, " quoteUsd: ",this.quoteUsd, "Wait 10 seconds then try again"); + await utils.sleep(10000); + await this.getNewMarketPrice(); + this.startOrderUpdater(); + } } else { this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); } @@ -89,38 +98,40 @@ class MarketMakerBot extends AbstractBot { } try { - this.counter ++; - console.log("000000000000000 COUNTER:",this.counter); - const startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); - const startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); - - - let bids: object[] = []; - let asks: object[] = []; - - this.orders.forEach((e,i)=>{ - if (e.side === 0){ - bids.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); - } else { - asks.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); + if (this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance))){ + this.counter ++; + console.log("000000000000000 COUNTER:",this.counter); + const startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); + const startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); + + + let bids: object[] = []; + let asks: object[] = []; + + console.log("UPDATE ORDERS - this.orders:", this.orders); + this.orders.forEach((e,i)=>{ + if (e.side === 0){ + bids.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); + } else { + asks.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); + } + }) + + let bidsSorted = sortOrders(bids, "price", "descending"); + let asksSorted = sortOrders(asks, "price", "ascending"); + + this.replaceBids(bidsSorted, startingBidPrice); + this.replaceAsks(asksSorted, startingAskPrice); + this.lastMarketPrice = this.marketPrice; } - }) - - let bidsSorted = sortOrders(bids, "price", "descending"); - let asksSorted = sortOrders(asks, "price", "ascending"); - - this.replaceBids(bidsSorted, startingBidPrice); - this.replaceAsks(asksSorted, startingAskPrice); - } catch (error) { this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); this.cleanUpAndExit(); } finally { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ - this.cleanUpAndExit(); - // await this.getNewMarketPrice(); - // this.updateOrders(); + await this.getNewMarketPrice(); + this.updateOrders(); }, this.interval); } } @@ -128,6 +139,7 @@ class MarketMakerBot extends AbstractBot { // Takes in an array of arrays. The first number of each subarray is the side, the second is the level. // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList async placeInitialOrders(levels: number[][]){ + console.log("PLACING INITAL ORDERS: ",levels); const initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); const initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); @@ -137,7 +149,7 @@ class MarketMakerBot extends AbstractBot { let asksEnRoute = 0; for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ - let bidPrice = new BigNumber(initialBidPrice * (1-(levels[x][1]*this.orderLevelSpread/100))); + let bidPrice = new BigNumber(initialBidPrice * (1-this.getSpread(levels[x][1]-1))); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ console.log("BID LEVEL ",levels[x][0],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); @@ -148,7 +160,7 @@ class MarketMakerBot extends AbstractBot { } } else { //--------------- SET ASKS --------------- // - let askPrice = new BigNumber(initialAskPrice * (1+(levels[x][1]*this.orderLevelSpread/100))); + let askPrice = new BigNumber(initialAskPrice * (1+this.getSpread(levels[x][1]-1))); let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioTot - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); @@ -172,11 +184,10 @@ class MarketMakerBot extends AbstractBot { for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ order = bidsSorted[j]; - console.log("BID ORDER: ", order); } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let bidPrice = new BigNumber(startingBidPrice * (1-(i*this.orderLevelSpread/100))); + let bidPrice = new BigNumber(startingBidPrice * (1-this.getSpread(i))); let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); @@ -186,7 +197,7 @@ class MarketMakerBot extends AbstractBot { console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); } } else { - console.log("MAKE FRESH ORDER"); + console.log("MAKE FRESH ORDER:", order.id,order.status); this.placeInitialOrders([[0,i+1]]); } } @@ -201,11 +212,10 @@ class MarketMakerBot extends AbstractBot { for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ order = asksSorted[j]; - console.log("ASK ORDER: ", order); } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let askPrice = new BigNumber(startingAskPrice * (1-(i*this.orderLevelSpread/100))); + let askPrice = new BigNumber(startingAskPrice * (1-this.getSpread(i))); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioTot + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); @@ -225,16 +235,16 @@ class MarketMakerBot extends AbstractBot { // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ - console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",(level) * this.orderLevelQty.toNumber()) - if ((level) * this.orderLevelQty.toNumber() < availableFunds){ - return (level) * this.orderLevelQty.toNumber(); + console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + if (this.getLevelQty(level) < availableFunds){ + return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 1.025){ return availableFunds*.975; } else { return 0;} } else if (side === 1) { - console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",(level) * this.orderLevelQty.toNumber()) - if ((level) * this.orderLevelQty.toNumber() < availableFunds){ - return (level) * this.orderLevelQty.toNumber(); + console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + if (this.getLevelQty(level) < availableFunds){ + return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 1.025){ return availableFunds * .975; } else {return 0;} @@ -243,23 +253,25 @@ class MarketMakerBot extends AbstractBot { } } + getLevelQty(level:number):number{ + return parseFloat(this.flatAmount) + (parseFloat(this.orderLevelQty) * (level-1)); + } + + getSpread(level:number):number{ + return (level*parseFloat(this.orderLevelSpread)/100) + } + // Update the marketPrice from an outside source async getNewMarketPrice() { try { - let response_base = await axios.get('http://localhost/'+this.base); - this.baseUsd = response_base.data; - - let response_quote = await axios.get('http://localhost/'+this.quote); - this.quoteUsd = response_quote.data; + let response = await axios.get('http://localhost:3000/prices'); + let prices = response.data; - if (!this.baseUsd){ //AVAX for testing - this.baseUsd = 12; - } - if (!this.quoteUsd){ //USDC for testing - this.quoteUsd = 1; - } + this.baseUsd = prices[this.base+'-USD']; + this.quoteUsd = prices[this.quote+'-USD']; this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); + console.log("new market Price:",this.marketPrice.toNumber()); } catch (error: any) { this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); } diff --git a/services/bots/classes.ts b/services/bots/classes.ts index fb5ca39..c255ffa 100644 --- a/services/bots/classes.ts +++ b/services/bots/classes.ts @@ -5,6 +5,7 @@ class NewOrder { public quantity: BigNumber; public price: BigNumber; public level: number; + public clientOrderId: any; constructor(side: number, quantity: BigNumber, price: BigNumber, level: number) { this.side = side; this.quantity = quantity; From debb8a0ad68aff5e99ece97025830a4896228cc7 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Fri, 14 Jul 2023 22:25:30 +0700 Subject: [PATCH 014/173] Order placing, updating, and tracking correctly. Set configuration in .env with logic for all pairs. Commented out some debug logs --- package.json | 11 +----- services/bots/AbstractBot.ts | 65 ++++++++++++++++++++------------- services/bots/MarketMakerBot.ts | 41 +++++++++++++-------- 3 files changed, 67 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index 4aa7829..14d54c5 100644 --- a/package.json +++ b/package.json @@ -8,15 +8,8 @@ "node": "16.15.1" }, "scripts": { - "sampleBot-hh": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=local-hh --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "sampleBot-dev": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=development --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "sampleBot-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "marketMakerBot-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "loadBot": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "loadBot1": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp@1 --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "loadBot2": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp@2 --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "loadBot3": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=multiapp@3 --ENCYRPT_SECRET=secret --ENCRYPT_SALT=salt", - "prepare": "node prepare.js" + "marketMaker-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji", + "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=development" }, "dependencies": { "@ethersproject/experimental": "5.7.0", diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 47db923..a18ac6f 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -423,7 +423,7 @@ abstract class AbstractBot { prices.push(priceToSend); quantities.push(quantityToSend); sides.push(newOrders[i].side); - type2s.push(0); + type2s.push(3); const order = this.makeOrder( this.account, @@ -435,7 +435,7 @@ abstract class AbstractBot { quantityToSend, newOrders[i].side, 1, - 0, //Buy , Limit, GTC + 0, //Buy , Limit, GTC 3 = post only 9, //PENDING status 0, 0, @@ -445,6 +445,7 @@ abstract class AbstractBot { 0, 0, newOrders[i].level, + new Date().getSeconds() ); this.addOrderToMap(order); @@ -533,13 +534,18 @@ abstract class AbstractBot { } } - async addOrder(side: number, qty: BigNumber | undefined, px: BigNumber | undefined, ordtype = 1, ordType2 = 0, level: number) { + async addOrder(side: number, qty: BigNumber | undefined, px: BigNumber | undefined, ordtype = 1, ordType2 = 3, level: number) { // LIMIT ORDER & GTC) if (!this.status) { return; } - const clientOrderId = await this.getClientOrderId(); + //get unique counter to generate clientOrderId + let counter = level; + if (level == 1){ + counter = counter + 100; + } + const clientOrderId = await this.getClientOrderId(0,counter); let price = px; let quantity = qty; @@ -619,6 +625,7 @@ abstract class AbstractBot { 0, 0, level, + new Date().getSeconds() ); this.addOrderToMap(order); @@ -713,7 +720,7 @@ abstract class AbstractBot { } const timestamp = new Date().toISOString(); if (this.account) { - const id = eutils.toUtf8Bytes(`${this.account}${this.tradePairByte32}${blocknumber}${timestamp}${counter}`); + const id = eutils.toUtf8Bytes(`${counter}${timestamp}${this.account}${this.tradePairByte32}${blocknumber}`); return eutils.keccak256(id); } return ""; @@ -943,7 +950,8 @@ abstract class AbstractBot { gasUsed: any, gasPrice: any, cumulativeGasUsed: any, - level: number = 0, + level: any, + timestamp: any ): any { return new Order({ id, @@ -969,6 +977,7 @@ abstract class AbstractBot { gasPrice: utils.formatUnits(gasPrice, 9), cumulativeGasUsed, level, + timestamp: new Date().getSeconds() }); } @@ -1018,7 +1027,8 @@ abstract class AbstractBot { tx.gasUsed.toString(), tx.effectiveGasPrice ? tx.effectiveGasPrice.toString() : "225", tx.cumulativeGasUsed.toString(), - level + level, + new Date().getSeconds() ); if (utils.statusMap[order.status] === "NEW" || utils.statusMap[order.status] === "PARTIAL") { @@ -1040,11 +1050,11 @@ abstract class AbstractBot { if (existingOrder) { if (order.status === existingOrder.status && order.quantityfilled.eq(existingOrder.quantityfilled)) { //The same Order event received from the txReceipt & also from the listener. Ignore - this.logger.debug( - `${this.instanceName} Duplicate Order event: ${order.clientOrderId} ${order.pair} ${ - order.side === 0 ? "BUY" : "SELL" - } ${order.quantity.toString()} @ ${order.price.toString()} ${utils.statusMap[order.status]}` - ); + // this.logger.debug( + // `${this.instanceName} Duplicate Order event: ${order.clientOrderId} ${order.pair} ${ + // order.side === 0 ? "BUY" : "SELL" + // } ${order.quantity.toString()} @ ${order.price.toString()} ${utils.statusMap[order.status]}` + // ); } else { // There is a change in the order if (order.quantityfilled.gt(existingOrder.quantityfilled)) { @@ -1195,16 +1205,16 @@ abstract class AbstractBot { async cancelOrder(order: any) { try { - const gasest = await this.getCancelOrderGasEstimate(order); + // const gasest = await this.getCancelOrderGasEstimate(order); - this.logger.debug(`${this.instanceName} Cancel order gasEstimate: ${gasest} `); // ${tcost} + // this.logger.debug(`${this.instanceName} Cancel order gasEstimate: ${gasest} `); // ${tcost} this.orderCount++; this.logger.debug( `${this.instanceName} canceling OrderNbr: ${this.orderCount} ${ order.side === 0 ? "BUY" : "SELL" } ::: ${order.quantity.toString()} ${this.base} @ ${order.price.toString()} ${this.quote}` ); - const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); + const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); const tx = await this.tradePair.cancelOrder(order.id, options); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); //const orderLog = await this.race({ promise: tx.wait(), count: this.orderCount} ); @@ -1295,7 +1305,7 @@ abstract class AbstractBot { const clientOrderId = await this.getClientOrderId(0,counter); // Not using the gasEstimate because it fails with P-AFNE1 when funds are tight but the actual C/R doesn't - console.log("CANCEL REPLACE: Orderid to replace:",order.id, " New clientOrderid: ", clientOrderId," PRICE:", price.toNumber(), " QTY: ", quantity.toNumber()); + console.log("CANCEL REPLACE: New clientOrderid: ", clientOrderId," PRICE:", price.toNumber(), " QTY: ", quantity.toNumber()); //const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); @@ -1308,7 +1318,7 @@ abstract class AbstractBot { order.side === 0 ? "BUY" : "SELL" } ::: ${quantity.toString()} ${this.base} @ ${price.toString()} ${this.quote}` ); - const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); + const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1500000)); const tx = await this.tradePair.cancelReplaceOrder(order.id, clientOrderId, priceToSend, quantityToSend, options); const orderLog = await tx.wait(); @@ -1419,19 +1429,22 @@ abstract class AbstractBot { async checkOrdersInChain() { const promises: any = []; const orders: any = []; + const time = new Date().getSeconds(); for (const order of this.orders.values()) { - orders.push(order); - promises.push(this.tradePair.getOrder(order.id)); + if (time - order.timestamp > 30){ + orders.push(order); + promises.push(this.tradePair.getOrder(order.id)); + } } try { const results = await Promise.all(promises); for (let i = 0; i < results.length; i++) { this.checkOrderInChain(orders[i], results[i]); - this.logger.debug( - `${this.instanceName} checkOrdersInChain: ${orders[i].side === 0 ? "BUY" : "SELL"} ${orders[i].quantity.toString()} ${ - this.base - } @ ${orders[i].price.toString()} ${utils.statusMap[orders[i].status]}` - ); + // this.logger.debug( + // `${this.instanceName} checkOrdersInChain: ${orders[i].side === 0 ? "BUY" : "SELL"} ${orders[i].quantity.toString()} ${ + // this.base + // } @ ${orders[i].price.toString()} ${utils.statusMap[orders[i].status]}` + // ); } } catch (error) { throw new Error("Could not fetch order status"); @@ -1458,7 +1471,9 @@ abstract class AbstractBot { "", "0", "0", - "0" + "0", + 0, + new Date().getSeconds() ); //tx, blocknbr , gasUsed, gasPrice, cumulativeGasUsed) ; const ordstatus = orderInChain.status; diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 080dd1f..7486100 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -24,13 +24,14 @@ class MarketMakerBot extends AbstractBot { super(botId, pairStr, privateKey); // Will try to rebalance the amounts in the Portfolio Contract this.portfolioRebalanceAtStart = false; - this.bidSpread = getConfig("bidSpread"); - this.askSpread = getConfig("askSpread"); - this.orderLevels = getConfig("orderLevels"); - this.orderLevelSpread = getConfig("orderLevelSpread"); - this.orderLevelQty = getConfig("orderLevelQty"); - this.refreshOrderTolerance = getConfig("refreshOrderTolerance"); - this.flatAmount = getConfig("flatAmount"); + this.config = getConfig(this.tradePairIdentifier) + this.bidSpread = this.config.bidSpread; + this.askSpread = this.config.askSpread + this.orderLevels = this.config.orderLevels + this.orderLevelSpread = this.config.orderLevelSpread + this.orderLevelQty = this.config.orderLevelQty + this.refreshOrderTolerance = this.config.refreshOrderTolerance + this.flatAmount = this.config.flatAmount } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -42,7 +43,7 @@ class MarketMakerBot extends AbstractBot { if (initializing) { await this.getNewMarketPrice(); - this.interval = 15000; //Min 10 seconds + this.interval = 10000; //Min 10 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -108,9 +109,10 @@ class MarketMakerBot extends AbstractBot { let bids: object[] = []; let asks: object[] = []; - console.log("UPDATE ORDERS - this.orders:", this.orders); this.orders.forEach((e,i)=>{ - if (e.side === 0){ + if (!e.level){ + this.cancelOrder(e); // Sometimes the level gets lost. I have no idea how. So I just delete the order and it will make a new one for that level. + } else if (e.side === 0){ bids.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); } else { asks.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); @@ -130,6 +132,7 @@ class MarketMakerBot extends AbstractBot { } finally { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ + await this.processOpenOrders(); await this.getNewMarketPrice(); this.updateOrders(); }, this.interval); @@ -173,14 +176,20 @@ class MarketMakerBot extends AbstractBot { } // // --------------- EXECUTE ORDERS --------------- // - await this.addLimitOrderList(newOrderList); + if (newOrderList.length == 0){ + console.log("ERROR - NewOrderList empty"); + } else if (newOrderList.length == 1){ + await this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); + } else { + await this.addLimitOrderList(newOrderList); + } } async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); let bidsEnRoute = 0; for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; + let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ order = bidsSorted[j]; @@ -191,7 +200,7 @@ class MarketMakerBot extends AbstractBot { let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); - console.log("REPLACE ORDER:",bidPrice,bidQty); + console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); this.cancelReplaceOrder(order,bidPrice,bidQty); } else { console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); @@ -208,18 +217,18 @@ class MarketMakerBot extends AbstractBot { let asksEnRoute = 0; for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0)}; + let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ order = asksSorted[j]; } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ - let askPrice = new BigNumber(startingAskPrice * (1-this.getSpread(i))); + let askPrice = new BigNumber(startingAskPrice * (1+this.getSpread(i))); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioTot + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); - console.log("REPLACE ORDER:",askPrice,askQty); + console.log("REPLACE ORDER:",askPrice,askQty, i+1); this.cancelReplaceOrder(order,askPrice,askQty); } else { console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); From 7ab37ec3448e413500e5625148fffcf62ae7fec2 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 15 Jul 2023 10:51:11 +0700 Subject: [PATCH 015/173] added timestamps to orders. Checks if orders haven't been updated in a while and runs this.processOrders(). Successfully removes duplicates and level 0 orders --- services/bots/AbstractBot.ts | 5 ++-- services/bots/MarketMakerBot.ts | 48 ++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index a18ac6f..145290e 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1414,7 +1414,8 @@ abstract class AbstractBot { totalfee: new BigNumber(order.totalfee), gasUsed: 0, gasPrice: 0, - cumulativeGasUsed: 0 + cumulativeGasUsed: 0, + timestamp: new Date().getSeconds(), }); this.addOrderToMap(orderfromDb); @@ -1447,7 +1448,7 @@ abstract class AbstractBot { // ); } } catch (error) { - throw new Error("Could not fetch order status"); + console.log("ERROR CHECKING ORDERS ON CHAIN:", error); } } diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 7486100..e28c07f 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -43,7 +43,7 @@ class MarketMakerBot extends AbstractBot { if (initializing) { await this.getNewMarketPrice(); - this.interval = 10000; //Min 10 seconds + this.interval = 15000; //Min 10 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -108,19 +108,21 @@ class MarketMakerBot extends AbstractBot { let bids: object[] = []; let asks: object[] = []; - + this.orders.forEach((e,i)=>{ - if (!e.level){ - this.cancelOrder(e); // Sometimes the level gets lost. I have no idea how. So I just delete the order and it will make a new one for that level. - } else if (e.side === 0){ + if (e.side == 0){ bids.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); - } else { + } else if (e.side == 1) { asks.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); + } else { + this.cancelOrder(e); // Sometimes the level gets lost. I have no idea how. So I just delete the order and it will make a new one for that level. } - }) + }); let bidsSorted = sortOrders(bids, "price", "descending"); let asksSorted = sortOrders(asks, "price", "ascending"); + + this.replaceBids(bidsSorted, startingBidPrice); this.replaceAsks(asksSorted, startingAskPrice); @@ -188,11 +190,17 @@ class MarketMakerBot extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); let bidsEnRoute = 0; + let skip = false; for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ - order = bidsSorted[j]; + if (order.id){ + this.cancelOrderList([order.id,bidsSorted[j].id]) + skip = true; + } else { + order = bidsSorted[j]; + } } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ @@ -206,8 +214,12 @@ class MarketMakerBot extends AbstractBot { console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); } } else { - console.log("MAKE FRESH ORDER:", order.id,order.status); - this.placeInitialOrders([[0,i+1]]); + if (!skip){ + console.log("MAKE FRESH ORDER:", order.id,order.status); + this.placeInitialOrders([[0,i+1]]); + } else { + console.log("SKIP BID, DELETING DUPLICATES"); + } } } } @@ -215,12 +227,18 @@ class MarketMakerBot extends AbstractBot { async replaceAsks (asksSorted: any, startingAskPrice: number){ console.log("REPLACE ASKS: ",asksSorted.length); let asksEnRoute = 0; + let skip = false; for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ - order = asksSorted[j]; + if (order.id){ + this.cancelOrderList([order.id,asksSorted[j].id]) + skip = true; + } else { + order = asksSorted[j]; + } } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ @@ -234,8 +252,12 @@ class MarketMakerBot extends AbstractBot { console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); } } else { - console.log("MAKE FRESH ORDER"); - this.placeInitialOrders([[1,i+1]]); + if (!skip){ + console.log("MAKE FRESH ORDER"); + this.placeInitialOrders([[1,i+1]]); + } else { + console.log("SKIP ASK, DELETING DUPLICATES"); + } } } } From acd45be9132b44e895a93c5327dc25530a457d65 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 15 Jul 2023 11:28:43 +0700 Subject: [PATCH 016/173] adjust startingbid and starting ask to avoid overlapping orders and postonly errors. Add precision to getMarketPrice to avoid orders with the same price. Unsure if I'll keep it. I think it's ready for its first production tests --- services/bots/MarketMakerBot.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index e28c07f..dfe450a 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -102,8 +102,20 @@ class MarketMakerBot extends AbstractBot { if (this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance))){ this.counter ++; console.log("000000000000000 COUNTER:",this.counter); - const startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); - const startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); + let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); + let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); + const myBestAsk = this.orderbook.bestask().price.toNumber(); + const myBestBid = this.orderbook.bestbid().price.toNumber(); + + // Don't want overlapping bids and asks. It would return errors since these are post only orders. + if (myBestAsk && startingBidPrice > myBestAsk){ + console.log("BEST ASK: ",myBestAsk, "STARTING BID PRICE: ", startingBidPrice) + startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread/100); + } + if (myBestBid && startingAskPrice < myBestBid){ + console.log("BEST BID: ",myBestBid, "STARTING ASK PRICE: ", startingAskPrice) + startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread/100); + } let bids: object[] = []; @@ -301,7 +313,7 @@ class MarketMakerBot extends AbstractBot { this.baseUsd = prices[this.base+'-USD']; this.quoteUsd = prices[this.quote+'-USD']; - this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); + this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd).dp(this.quoteDisplayDecimals); console.log("new market Price:",this.marketPrice.toNumber()); } catch (error: any) { this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); From 3c76b19aa8cd7668b1ff636ff5e7a3574e9ca44e Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 15 Jul 2023 13:15:47 +0700 Subject: [PATCH 017/173] improve overlapping order avoidance in the order updater and added timer for waiting after replacing orders --- services/bots/AbstractBot.ts | 2 +- services/bots/MarketMakerBot.ts | 77 +++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 145290e..2795ce2 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1432,7 +1432,7 @@ abstract class AbstractBot { const orders: any = []; const time = new Date().getSeconds(); for (const order of this.orders.values()) { - if (time - order.timestamp > 30){ + if (time - order.timestamp > this.interval){ // If the order hasn't been updated within the interval time, check the chain to make sure we're not missing any information about it. orders.push(order); promises.push(this.tradePair.getOrder(order.id)); } diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index dfe450a..bd18a13 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -19,19 +19,20 @@ class MarketMakerBot extends AbstractBot { protected orderLevelQty: any; protected refreshOrderTolerance: any; protected flatAmount: any; + protected timer: any; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); // Will try to rebalance the amounts in the Portfolio Contract this.portfolioRebalanceAtStart = false; - this.config = getConfig(this.tradePairIdentifier) - this.bidSpread = this.config.bidSpread; - this.askSpread = this.config.askSpread - this.orderLevels = this.config.orderLevels - this.orderLevelSpread = this.config.orderLevelSpread - this.orderLevelQty = this.config.orderLevelQty - this.refreshOrderTolerance = this.config.refreshOrderTolerance - this.flatAmount = this.config.flatAmount + this.config = getConfig(this.tradePairIdentifier); + this.bidSpread = this.config.bidSpread/100; + this.askSpread = this.config.askSpread/100; + this.orderLevels = this.config.orderLevels; + this.orderLevelSpread = this.config.orderLevelSpread/100; + this.orderLevelQty = this.config.orderLevelQty; + this.refreshOrderTolerance = this.config.refreshOrderTolerance/100; + this.flatAmount = this.config.flatAmount; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -43,7 +44,7 @@ class MarketMakerBot extends AbstractBot { if (initializing) { await this.getNewMarketPrice(); - this.interval = 15000; //Min 10 seconds + this.interval = 10000; //Min 10 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -101,23 +102,13 @@ class MarketMakerBot extends AbstractBot { try { if (this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance))){ this.counter ++; + this.timer = this.interval; console.log("000000000000000 COUNTER:",this.counter); - let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); - let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); + let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); + let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); const myBestAsk = this.orderbook.bestask().price.toNumber(); const myBestBid = this.orderbook.bestbid().price.toNumber(); - // Don't want overlapping bids and asks. It would return errors since these are post only orders. - if (myBestAsk && startingBidPrice > myBestAsk){ - console.log("BEST ASK: ",myBestAsk, "STARTING BID PRICE: ", startingBidPrice) - startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread/100); - } - if (myBestBid && startingAskPrice < myBestBid){ - console.log("BEST BID: ",myBestBid, "STARTING ASK PRICE: ", startingAskPrice) - startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread/100); - } - - let bids: object[] = []; let asks: object[] = []; @@ -134,10 +125,28 @@ class MarketMakerBot extends AbstractBot { let bidsSorted = sortOrders(bids, "price", "descending"); let asksSorted = sortOrders(asks, "price", "ascending"); + // If there will be overlapping orders, wait for the orders of the side in which the price moved to be replaced first, then follow with the others. + if (myBestAsk && startingBidPrice > myBestAsk){ + console.log("BEST ASK: ",myBestAsk, "STARTING BID PRICE: ", startingBidPrice) + //startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread); + + await this.replaceAsks(asksSorted, startingAskPrice); + setTimeout (async()=>{ + await this.replaceBids(bidsSorted, startingBidPrice); + }, 4000) + + } else if (myBestBid && startingAskPrice < myBestBid){ + console.log("BEST BID: ",myBestBid, "STARTING ASK PRICE: ", startingAskPrice) + //startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread); + + await this.replaceBids(bidsSorted, startingBidPrice); + setTimeout (async()=>{ + await this.replaceAsks(asksSorted, startingAskPrice); + }, 4000) - - this.replaceBids(bidsSorted, startingBidPrice); - this.replaceAsks(asksSorted, startingAskPrice); + } else { + await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + } this.lastMarketPrice = this.marketPrice; } } catch (error) { @@ -146,10 +155,12 @@ class MarketMakerBot extends AbstractBot { } finally { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ - await this.processOpenOrders(); - await this.getNewMarketPrice(); - this.updateOrders(); - }, this.interval); + if (this.status){ + await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice()]); + this.timer = 2000; + this.updateOrders(); + } + }, this.timer); } } @@ -158,8 +169,8 @@ class MarketMakerBot extends AbstractBot { async placeInitialOrders(levels: number[][]){ console.log("PLACING INITAL ORDERS: ",levels); - const initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread/100); - const initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread/100); + const initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); + const initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // let bidsEnroute = 0; @@ -301,7 +312,7 @@ class MarketMakerBot extends AbstractBot { } getSpread(level:number):number{ - return (level*parseFloat(this.orderLevelSpread)/100) + return (level*parseFloat(this.orderLevelSpread)) } // Update the marketPrice from an outside source @@ -313,7 +324,7 @@ class MarketMakerBot extends AbstractBot { this.baseUsd = prices[this.base+'-USD']; this.quoteUsd = prices[this.quote+'-USD']; - this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd).dp(this.quoteDisplayDecimals); + this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); console.log("new market Price:",this.marketPrice.toNumber()); } catch (error: any) { this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); From 32cca8f81ca53bcd7094f3e1af167433925359e2 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 16 Jul 2023 17:57:42 +0700 Subject: [PATCH 018/173] updated dependencies, fixed issues with duplicating orders and overlapping orders. executes shutdown when triggering an unhandled error --- package.json | 3 - services/bots/AbstractBot.ts | 68 +- services/bots/BotFactory.ts | 5 +- services/bots/MarketMakerBot.ts | 102 +- services/bots/botLauncher.ts | 1 + yarn.lock | 4864 +++++++++++++++---------------- 6 files changed, 2527 insertions(+), 2516 deletions(-) diff --git a/package.json b/package.json index 14d54c5..943cbfc 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,6 @@ "license": "MIT", "private": true, "author": "Cengiz Dincoglu", - "engines": { - "node": "16.15.1" - }, "scripts": { "marketMaker-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji", "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=development" diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 2795ce2..196717a 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -333,7 +333,7 @@ abstract class AbstractBot { if (this.orderUpdater !== undefined) { clearTimeout(this.orderUpdater); } - this.cancelOrderList() + this.cancelOrderList([], 100) .then(() => { this.logger.warn(`${this.instanceName} Waiting 5 seconds before removing order listeners"...`); setTimeout(async () => { @@ -587,18 +587,18 @@ abstract class AbstractBot { this.orderCount++; - const gasest = await this.getAddOrderGasEstimate(clientOrderId, price, quantity, side, ordtype, ordType2); + //const gasest = await this.getAddOrderGasEstimate(clientOrderId, price, quantity, side, ordtype, ordType2); // const tcost = await this.getTCost(gasest); // this.logger.debug (`${this.instanceName} New order gasEstimate: ${gasest} , tcost ${tcost.toString()} `); - this.logger.debug( - `${this.instanceName} SENDING ORDER OrderNbr: ${this.orderCount} ${side === 0 ? "BUY" : "SELL"}::: ${quantity.toFixed( - this.baseDisplayDecimals - )} ${this.base} @ ${ordtype === 0 ? "MARKET" : price.toFixed(this.quoteDisplayDecimals)} ${this.quote}` - ); + // this.logger.debug( + // `${this.instanceName} SENDING ORDER OrderNbr: ${this.orderCount} ${side === 0 ? "BUY" : "SELL"}::: ${quantity.toFixed( + // this.baseDisplayDecimals + // )} ${this.base} @ ${ordtype === 0 ? "MARKET" : price.toFixed(this.quoteDisplayDecimals)} ${this.quote}` + // ); // this.logger.info (`${utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals)}`); // this.logger.info (`${utils.parseUnits(quantity.toFixed(this.baseDisplayDecimals), this.contracts[this.base].tokenDetails.evmdecimals)}`); - const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); + const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); const priceToSend = utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals); const quantityToSend = utils.parseUnits( @@ -1138,7 +1138,9 @@ abstract class AbstractBot { if (orderIds.length === 0) { let i = 0; for (const order of this.orders.values()) { - orderIds.push(order.id); + if (order.id){ + orderIds.push(order.id); + } i++; if (i >= nbrofOrderstoCancel) { // More than xx orders in a cancel will run out of gas @@ -1397,29 +1399,33 @@ abstract class AbstractBot { async processOpenOrders() { this.logger.info(`${this.instanceName} Recovering open orders:`); const orders = await this.getOpenOrders(); - for (const order of orders) { - const orderfromDb = new Order({ - id: order.id, - clientOrderId: order.clientordid, - traderaddress: order.traderaddress, - quantity: new BigNumber(order.quantity), - pair: order.pair, - price: new BigNumber(order.price), - side: parseInt(order.side), - type: parseInt(order.type), - type2: parseInt(order.type2), - status: parseInt(order.status), - quantityfilled: new BigNumber(order.quantityfilled), - totalamount: new BigNumber(order.totalamount), - totalfee: new BigNumber(order.totalfee), - gasUsed: 0, - gasPrice: 0, - cumulativeGasUsed: 0, - timestamp: new Date().getSeconds(), - }); - - this.addOrderToMap(orderfromDb); + if (orders){ + for (const order of orders) { + const orderfromDb = new Order({ + id: order.id, + clientOrderId: order.clientordid, + traderaddress: order.traderaddress, + quantity: new BigNumber(order.quantity), + pair: order.pair, + price: new BigNumber(order.price), + side: parseInt(order.side), + type: parseInt(order.type), + type2: parseInt(order.type2), + status: parseInt(order.status), + quantityfilled: new BigNumber(order.quantityfilled), + totalamount: new BigNumber(order.totalamount), + totalfee: new BigNumber(order.totalfee), + gasUsed: 0, + gasPrice: 0, + cumulativeGasUsed: 0, + level: -1, + timestamp: new Date().getSeconds() + }); + + this.addOrderToMap(orderfromDb); + } } + await this.checkOrdersInChain(); this.logger.info(`${this.instanceName} open orders recovered:`); return true; diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index 9a1b0ac..3652c26 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -1,9 +1,8 @@ import MarketMakerBot from "./MarketMakerBot"; -const Bot:any = {MarketMakerBot}; +const Bot:any = MarketMakerBot; module.exports = { createBot(type:any, attributes:any) { - const BotType = Bot[type]; - return new BotType(attributes.botId,attributes.pairStr,attributes.privateKey); + return new Bot(attributes.botId,attributes.pairStr,attributes.privateKey); } }; diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index bd18a13..58f9306 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -44,7 +44,7 @@ class MarketMakerBot extends AbstractBot { if (initializing) { await this.getNewMarketPrice(); - this.interval = 10000; //Min 10 seconds + this.interval = 150000; //Min 10 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -82,7 +82,7 @@ class MarketMakerBot extends AbstractBot { this.orderUpdater = setTimeout(()=>{ this.lastMarketPrice = this.marketPrice; this.updateOrders(); - }, this.interval/2); + }, this.interval); } else { console.log("MISSING PRICE DATA - baseUsd:",this.baseUsd, " quoteUsd: ",this.quoteUsd, "Wait 10 seconds then try again"); await utils.sleep(10000); @@ -106,43 +106,65 @@ class MarketMakerBot extends AbstractBot { console.log("000000000000000 COUNTER:",this.counter); let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); - const myBestAsk = this.orderbook.bestask().price.toNumber(); - const myBestBid = this.orderbook.bestbid().price.toNumber(); + const myBestAsk = this.orderbook.bestask() ? this.orderbook.bestask().price.toNumber() : undefined; + const myBestBid = this.orderbook.bestbid() ? this.orderbook.bestbid().price.toNumber() : undefined; - let bids: object[] = []; - let asks: object[] = []; + let bids: any[] = []; + let asks: any[] = []; + let duplicates: any[] = []; this.orders.forEach((e,i)=>{ - if (e.side == 0){ - bids.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); - } else if (e.side == 1) { - asks.push({side:e.side,id:e.id,price:e.price.toNumber(),level:e.level,status:e.status, totalamount:e.totalamount,quantityfilled:e.quantityfilled}); + if (e.side === 0){ + let skip = false; + for (let i = 0;i 0){ + this.cancelOrderList(duplicates); + } let bidsSorted = sortOrders(bids, "price", "descending"); let asksSorted = sortOrders(asks, "price", "ascending"); + console.log(bidsSorted); + console.log(asksSorted); // If there will be overlapping orders, wait for the orders of the side in which the price moved to be replaced first, then follow with the others. if (myBestAsk && startingBidPrice > myBestAsk){ console.log("BEST ASK: ",myBestAsk, "STARTING BID PRICE: ", startingBidPrice) - //startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread); + startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread); await this.replaceAsks(asksSorted, startingAskPrice); - setTimeout (async()=>{ - await this.replaceBids(bidsSorted, startingBidPrice); - }, 4000) + await this.replaceBids(bidsSorted, startingBidPrice); } else if (myBestBid && startingAskPrice < myBestBid){ console.log("BEST BID: ",myBestBid, "STARTING ASK PRICE: ", startingAskPrice) - //startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread); + startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread); await this.replaceBids(bidsSorted, startingBidPrice); - setTimeout (async()=>{ - await this.replaceAsks(asksSorted, startingAskPrice); - }, 4000) + await this.replaceAsks(asksSorted, startingAskPrice); } else { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); @@ -156,7 +178,7 @@ class MarketMakerBot extends AbstractBot { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ if (this.status){ - await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice()]); + await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice(),this.correctNonce(this.contracts["SubNetProvider"])]); this.timer = 2000; this.updateOrders(); } @@ -180,7 +202,7 @@ class MarketMakerBot extends AbstractBot { let bidPrice = new BigNumber(initialBidPrice * (1-this.getSpread(levels[x][1]-1))); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - console.log("BID LEVEL ",levels[x][0],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); + console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); bidsEnroute += bidQty.toNumber(); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } else { @@ -204,9 +226,13 @@ class MarketMakerBot extends AbstractBot { if (newOrderList.length == 0){ console.log("ERROR - NewOrderList empty"); } else if (newOrderList.length == 1){ - await this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); + if (this.status){ + await this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); + } } else { - await this.addLimitOrderList(newOrderList); + if (this.status){ + await this.addLimitOrderList(newOrderList); + } } } @@ -218,12 +244,7 @@ class MarketMakerBot extends AbstractBot { let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ - if (order.id){ - this.cancelOrderList([order.id,bidsSorted[j].id]) - skip = true; - } else { - order = bidsSorted[j]; - } + order = bidsSorted[j]; } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ @@ -237,12 +258,8 @@ class MarketMakerBot extends AbstractBot { console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); } } else { - if (!skip){ - console.log("MAKE FRESH ORDER:", order.id,order.status); - this.placeInitialOrders([[0,i+1]]); - } else { - console.log("SKIP BID, DELETING DUPLICATES"); - } + console.log("MAKE FRESH ORDER:", order.id,order.status); + this.placeInitialOrders([[0,i+1]]); } } } @@ -256,12 +273,7 @@ class MarketMakerBot extends AbstractBot { let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ - if (order.id){ - this.cancelOrderList([order.id,asksSorted[j].id]) - skip = true; - } else { - order = asksSorted[j]; - } + order = asksSorted[j]; } } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ @@ -275,12 +287,8 @@ class MarketMakerBot extends AbstractBot { console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); } } else { - if (!skip){ - console.log("MAKE FRESH ORDER"); - this.placeInitialOrders([[1,i+1]]); - } else { - console.log("SKIP ASK, DELETING DUPLICATES"); - } + console.log("MAKE FRESH ORDER"); + this.placeInitialOrders([[1,i+1]]); } } } diff --git a/services/bots/botLauncher.ts b/services/bots/botLauncher.ts index 88e34e8..3fb5b03 100644 --- a/services/bots/botLauncher.ts +++ b/services/bots/botLauncher.ts @@ -37,4 +37,5 @@ process.on("uncaughtException", (error) => { process.on("unhandledRejection", (error, promise) => { console.log(`BotManager We forgot to handle a promise rejection here:`, promise); console.log(`BotManager The error was:`, error); + bot.cleanUpAndExit(); }); diff --git a/yarn.lock b/yarn.lock index ab3ddb1..daf49e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,2432 +1,2432 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - -"@dabh/diagnostics@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" - integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== - dependencies: - colorspace "1.1.x" - enabled "2.0.x" - kuler "^2.0.0" - -"@eslint/eslintrc@^1.4.0": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" - integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/experimental@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" - integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== - dependencies: - "@ethersproject/web" "^5.7.0" - ethers "^5.7.0" - scrypt-js "3.0.1" - -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.5.0": - version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@humanwhocodes/config-array@^0.11.8": - version "0.11.10" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" - integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@types/axios@0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46" - integrity sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ== - dependencies: - axios "*" - -"@types/bintrees@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/bintrees/-/bintrees-1.0.3.tgz#44723d00ec44cc9a6607efd93f6d9837b26d8c48" - integrity sha512-A/LCJoFzbF6TIfRZ6IzWHaxthLSGj2qiOXiIWn4xjjbaZIZ8+97SUzgIU8E/n1v2ozc2aDGdzwkA2hfXozgKNg== - -"@types/chai@4.3.4": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" - integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== - -"@types/json-schema@^7.0.9": - version "7.0.12" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" - integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== - -"@types/mocha@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" - integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== - -"@types/moment-timezone@0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@types/moment-timezone/-/moment-timezone-0.5.3.tgz#66aecb4e8291c2bcf4fad9bfd51367c1edbd80c6" - integrity sha512-FdnK7nZZXkSDO2InIBociTYbsEOLN/NijlNevFcB1vexHuh9lRGwdbClTQAI3eH1clJmwdQ7Q+jOSv9H3EJTJw== - dependencies: - moment ">=2.14.0" - -"@types/nconf@0.10.3": - version "0.10.3" - resolved "https://registry.yarnpkg.com/@types/nconf/-/nconf-0.10.3.tgz#c4482389412ad534bcf11635c7e0a645ddac62d2" - integrity sha512-leyIuBk/rMIp9114FlPRkc/cQG+/JzCz1Afx3BD+CwK2ep3ZRxoC843V1rqnE2pC/jRRjANWhuVBEn4clCwlug== - -"@types/node@*": - version "20.4.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.1.tgz#a6033a8718653c50ac4962977e14d0f984d9527d" - integrity sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg== - -"@types/node@16.11.13": - version "16.11.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.13.tgz#6b71641b81a98c6a538d89892440c06f147edddc" - integrity sha512-eUXZzHLHoZqj1frtUetNkUetYoJ6X55UmrVnFD4DMhVeAmwLjniZhtBmsRiemQh4uq4G3vUra/Ws/hs9vEvL3Q== - -"@types/semver@^7.3.12": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" - integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== - -"@types/triple-beam@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.2.tgz#38ecb64f01aa0d02b7c8f4222d7c38af6316fef8" - integrity sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g== - -"@types/winston@2.4.4": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.4.4.tgz#48cc744b7b42fad74b9a2e8490e0112bd9a3d08d" - integrity sha512-BVGCztsypW8EYwJ+Hq+QNYiT/MUyCif0ouBH+flrY66O5W+KIXAMML6E/0fJpm7VjIzgangahl5S03bJJQGrZw== - dependencies: - winston "*" - -"@types/ws@8.5.3": - version "8.5.3" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" - integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== - dependencies: - "@types/node" "*" - -"@typescript-eslint/eslint-plugin@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz#50cc5085578a7fa22cd46a0806c2e5eae858af02" - integrity sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/type-utils" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.1.tgz#c4bf16f8c3c7608ce4bf8ff804b677fc899f173f" - integrity sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz#0d302b3c2f20ab24e4787bf3f5a0d8c449b823bd" - integrity sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - -"@typescript-eslint/type-utils@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz#aee13314f840ab336c1adb49a300856fd16d04ce" - integrity sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w== - dependencies: - "@typescript-eslint/typescript-estree" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.1.tgz#459f07428aec5a8c4113706293c2ae876741ac8e" - integrity sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A== - -"@typescript-eslint/typescript-estree@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz#b9d8441308aca53df7f69b2c67a887b82c9ed418" - integrity sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - 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.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.1.tgz#595f25ac06e9ee28c339fd43c709402820b13d7b" - integrity sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw== - dependencies: - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz#d35c2da544dbb685db9c5b5b85adac0a1d74d1f2" - integrity sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig== - dependencies: - "@typescript-eslint/types" "5.47.1" - eslint-visitor-keys "^3.3.0" - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.9.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== - -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -assert@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" - integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== - dependencies: - es6-object-assign "^1.1.0" - is-nan "^1.2.1" - object-is "^1.0.1" - util "^0.12.0" - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -async@^3.0.0, async@^3.2.0, async@^3.2.3: - version "3.2.4" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" - integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -axios@*: - version "1.4.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" - integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.1.tgz#44cf04a3c9f0c2252ebd85975361c026cb9f864a" - integrity sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - -bignumber.js@9.1.1, bignumber.js@^9.0.1: - version "9.1.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" - integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bintrees@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" - integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw== - -bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -chai@4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" - pathval "^1.1.1" - type-detect "^4.0.5" - -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== - -chokidar@3.5.3, chokidar@^3.5.2: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -color-convert@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.6.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" - integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.1.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" - integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== - dependencies: - color-convert "^1.9.3" - color-string "^1.6.0" - -colorspace@1.1.x: - version "1.1.4" - resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" - integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== - dependencies: - color "^3.1.3" - text-hex "1.0.x" - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -deep-eql@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" - integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== - dependencies: - type-detect "^4.0.0" - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-properties@^1.1.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -eip1559-fee-suggestions-ethers@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/eip1559-fee-suggestions-ethers/-/eip1559-fee-suggestions-ethers-1.3.3.tgz#cf21b6ae4734b697c8f79e556d91aeda3e464d60" - integrity sha512-W/5SQICRpDL0XvOdcX5oVWfaE2sow2u9il8I6Qyd9fkL9XY1knypywTcoBTdU9ULrPoP3phn/RnEKGq7Y8qkLw== - dependencies: - "@ethersproject/providers" "^5.5.0" - bignumber.js "^9.0.1" - ethers "^5.4.2" - moving-averages "^4.0.6" - -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -enabled@2.0.x: - version "2.0.0" - resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" - integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== - -es6-object-assign@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" - integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" - integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== - -eslint@8.30.0: - version "8.30.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" - integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ== - dependencies: - "@eslint/eslintrc" "^1.4.0" - "@humanwhocodes/config-array" "^0.11.8" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^9.4.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f" - integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esquery@^1.4.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -ethers@5.7.2, ethers@^5.4.2, ethers@^5.7.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9: - version "3.3.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" - integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== - dependencies: - reusify "^1.0.4" - -fecha@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" - integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@5.0.0, find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== - -fn.name@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" - integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== - -follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.3: - 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.19.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -ignore-by-default@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== - -ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== - -immediate@~3.0.5: - version "3.0.6" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" - integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-callable@^1.1.3: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-nan@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" - integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-typed-array@^1.1.10, is-typed-array@^1.1.3: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -js-sdsl@^4.1.4: - version "4.4.1" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.1.tgz#9e3c7b566d8d9a7e1fe8fc26d00b5ab0f8918ab3" - integrity sha512-6Gsx8R0RucyePbWqPssR8DyfuXmLBooYN5cZFZKjHGnQuaf7pEzhtpceagJxVu4LqhYY5EYA7nko3FmeHZ1KbA== - -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-yaml@4.1.0, js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -jszip@^3.2.2: - version "3.10.1" - resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" - integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== - dependencies: - lie "~3.3.0" - pako "~1.0.2" - readable-stream "~2.3.6" - setimmediate "^1.0.5" - -kuler@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" - integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lie@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" - integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== - dependencies: - immediate "~3.0.5" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -log-symbols@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - -logform@^2.3.2, logform@^2.4.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b" - integrity sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg== - dependencies: - "@colors/colors" "1.5.0" - "@types/triple-beam" "^1.3.2" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^2.3.1" - triple-beam "^1.3.0" - -loupe@^2.3.1: - version "2.3.6" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" - integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== - dependencies: - get-func-name "^2.0.0" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -mocha@10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" - integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - -moment-timezone@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.3.tgz#34ba53bd719677975bee9d0e8ba799ad9373f082" - integrity sha512-CruicnN/CSlOKDfyI+lQXZru32gIRGX1wF5PgW3sImRpAwo+kj/XkDVQ4shkU/GOcpigZUsJjOcBpuIZAqaROA== - dependencies: - moment ">= 2.6.0" - -"moment@>= 2.6.0", moment@>=2.14.0: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - -moving-averages@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/moving-averages/-/moving-averages-4.0.6.tgz#4978d4d9f68aef8f2b5fa028b1ec316da0cc8c95" - integrity sha512-Jv+mH0emTFP40Q5ONsBqTfIO9NuUyK9zuW4pWbOzWJm8jEqpLBtAH2CnE2MFIuH/G9f9nDugmnDVUJaHx9jckw== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - -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.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -nconf@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/nconf/-/nconf-0.12.0.tgz#9cf70757aae4d440d43ed53c42f87da18471b8bf" - integrity sha512-T3fZPw3c7Dfrz8JBQEbEcZJ2s8f7cUMpKuyBtsGQe0b71pcXx6gNh4oti2xh5dxB+gO9ufNfISBlGvvWtfyMcA== - dependencies: - async "^3.0.0" - ini "^2.0.0" - secure-keys "^1.0.0" - yargs "^16.1.1" - -nodemon@2.0.20: - version "2.0.20" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.20.tgz#e3537de768a492e8d74da5c5813cb0c7486fc701" - integrity sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw== - dependencies: - chokidar "^3.5.2" - debug "^3.2.7" - ignore-by-default "^1.0.1" - minimatch "^3.1.2" - pstree.remy "^1.1.8" - semver "^5.7.1" - simple-update-notifier "^1.0.7" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.5" - -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== - dependencies: - abbrev "1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -one-time@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" - integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== - dependencies: - fn.name "1.x.x" - -optionator@^0.9.1: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -pako@~1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -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" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -pstree.remy@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" - integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== - -punycode@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@3.0.2, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-stable-stringify@^2.3.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" - integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== - -scrypt-js@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -secure-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/secure-keys/-/secure-keys-1.0.0.tgz#f0c82d98a3b139a8776a8808050b824431087fca" - integrity sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg== - -semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^7.3.7: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -semver@~7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== - dependencies: - is-arrayish "^0.3.1" - -simple-update-notifier@^1.0.7: - version "1.1.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" - integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== - dependencies: - semver "~7.0.0" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -touch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" - integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== - dependencies: - nopt "~1.0.10" - -triple-beam@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" - integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== - -tsc@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/tsc/-/tsc-2.0.4.tgz#5f6499146abea5dca4420b451fa4f2f9345238f5" - integrity sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q== - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -typescript@4.8.4: - version "4.8.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" - integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== - -undefsafe@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" - integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -util@^0.12.0: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -which-typed-array@^1.1.2: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -winston-transport@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" - integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== - dependencies: - logform "^2.3.2" - readable-stream "^3.6.0" - triple-beam "^1.3.0" - -winston@*: - version "3.9.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.9.0.tgz#2bbdeb8167a75fac6d9a0c6d002890cd908016c2" - integrity sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ== - dependencies: - "@colors/colors" "1.5.0" - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.4.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.5.0" - -winston@3.8.2: - version "3.8.2" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.8.2.tgz#56e16b34022eb4cff2638196d9646d7430fdad50" - integrity sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew== - dependencies: - "@colors/colors" "1.5.0" - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.4.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.5.0" - -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - -ws@8.11.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0, yargs@^16.1.1: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zip-dir@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/zip-dir/-/zip-dir-2.0.0.tgz#c5df6e15c8f9efeb4e320377028c9f5c8277c932" - integrity sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg== - dependencies: - async "^3.2.0" - jszip "^3.2.2" +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@dabh/diagnostics@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== + dependencies: + colorspace "1.1.x" + enabled "2.0.x" + kuler "^2.0.0" + +"@eslint/eslintrc@^1.4.0": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" + integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.4.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/experimental@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/experimental/-/experimental-5.7.0.tgz#9759639434d37beaedfd8acab6f3af7db246b92d" + integrity sha512-DWvhuw7Dg8JPyhMbh/CNYOwsTLjXRx/HGkacIL5rBocG8jJC0kmixwoK/J3YblO4vtcyBLMa+sV74RJZK2iyHg== + dependencies: + "@ethersproject/web" "^5.7.0" + ethers "^5.7.0" + scrypt-js "3.0.1" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.5.0": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@humanwhocodes/config-array@^0.11.8": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@types/axios@0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46" + integrity sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ== + dependencies: + axios "*" + +"@types/bintrees@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@types/bintrees/-/bintrees-1.0.3.tgz#44723d00ec44cc9a6607efd93f6d9837b26d8c48" + integrity sha512-A/LCJoFzbF6TIfRZ6IzWHaxthLSGj2qiOXiIWn4xjjbaZIZ8+97SUzgIU8E/n1v2ozc2aDGdzwkA2hfXozgKNg== + +"@types/chai@4.3.4": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" + integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== + +"@types/json-schema@^7.0.9": + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== + +"@types/mocha@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" + integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== + +"@types/moment-timezone@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@types/moment-timezone/-/moment-timezone-0.5.3.tgz#66aecb4e8291c2bcf4fad9bfd51367c1edbd80c6" + integrity sha512-FdnK7nZZXkSDO2InIBociTYbsEOLN/NijlNevFcB1vexHuh9lRGwdbClTQAI3eH1clJmwdQ7Q+jOSv9H3EJTJw== + dependencies: + moment ">=2.14.0" + +"@types/nconf@0.10.3": + version "0.10.3" + resolved "https://registry.yarnpkg.com/@types/nconf/-/nconf-0.10.3.tgz#c4482389412ad534bcf11635c7e0a645ddac62d2" + integrity sha512-leyIuBk/rMIp9114FlPRkc/cQG+/JzCz1Afx3BD+CwK2ep3ZRxoC843V1rqnE2pC/jRRjANWhuVBEn4clCwlug== + +"@types/node@*": + version "20.4.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9" + integrity sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw== + +"@types/node@16.11.13": + version "16.11.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.13.tgz#6b71641b81a98c6a538d89892440c06f147edddc" + integrity sha512-eUXZzHLHoZqj1frtUetNkUetYoJ6X55UmrVnFD4DMhVeAmwLjniZhtBmsRiemQh4uq4G3vUra/Ws/hs9vEvL3Q== + +"@types/semver@^7.3.12": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + +"@types/triple-beam@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.2.tgz#38ecb64f01aa0d02b7c8f4222d7c38af6316fef8" + integrity sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g== + +"@types/winston@2.4.4": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.4.4.tgz#48cc744b7b42fad74b9a2e8490e0112bd9a3d08d" + integrity sha512-BVGCztsypW8EYwJ+Hq+QNYiT/MUyCif0ouBH+flrY66O5W+KIXAMML6E/0fJpm7VjIzgangahl5S03bJJQGrZw== + dependencies: + winston "*" + +"@types/ws@8.5.3": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== + dependencies: + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@5.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz#50cc5085578a7fa22cd46a0806c2e5eae858af02" + integrity sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg== + dependencies: + "@typescript-eslint/scope-manager" "5.47.1" + "@typescript-eslint/type-utils" "5.47.1" + "@typescript-eslint/utils" "5.47.1" + debug "^4.3.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@5.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.1.tgz#c4bf16f8c3c7608ce4bf8ff804b677fc899f173f" + integrity sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw== + dependencies: + "@typescript-eslint/scope-manager" "5.47.1" + "@typescript-eslint/types" "5.47.1" + "@typescript-eslint/typescript-estree" "5.47.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz#0d302b3c2f20ab24e4787bf3f5a0d8c449b823bd" + integrity sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw== + dependencies: + "@typescript-eslint/types" "5.47.1" + "@typescript-eslint/visitor-keys" "5.47.1" + +"@typescript-eslint/type-utils@5.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz#aee13314f840ab336c1adb49a300856fd16d04ce" + integrity sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w== + dependencies: + "@typescript-eslint/typescript-estree" "5.47.1" + "@typescript-eslint/utils" "5.47.1" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.1.tgz#459f07428aec5a8c4113706293c2ae876741ac8e" + integrity sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A== + +"@typescript-eslint/typescript-estree@5.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz#b9d8441308aca53df7f69b2c67a887b82c9ed418" + integrity sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA== + dependencies: + "@typescript-eslint/types" "5.47.1" + "@typescript-eslint/visitor-keys" "5.47.1" + 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.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.1.tgz#595f25ac06e9ee28c339fd43c709402820b13d7b" + integrity sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw== + dependencies: + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.47.1" + "@typescript-eslint/types" "5.47.1" + "@typescript-eslint/typescript-estree" "5.47.1" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.47.1": + version "5.47.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz#d35c2da544dbb685db9c5b5b85adac0a1d74d1f2" + integrity sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig== + dependencies: + "@typescript-eslint/types" "5.47.1" + eslint-visitor-keys "^3.3.0" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +assert@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" + integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== + dependencies: + es6-object-assign "^1.1.0" + is-nan "^1.2.1" + object-is "^1.0.1" + util "^0.12.0" + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +async@^3.0.0, async@^3.2.0, async@^3.2.3: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +axios@*: + version "1.4.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.1.tgz#44cf04a3c9f0c2252ebd85975361c026cb9f864a" + integrity sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bignumber.js@9.1.1, bignumber.js@^9.0.1: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bintrees@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" + integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chai@4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chokidar@3.5.3, chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.6.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.1.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + +colorspace@1.1.x: + version "1.1.4" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" + integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== + dependencies: + color "^3.1.3" + text-hex "1.0.x" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-properties@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +eip1559-fee-suggestions-ethers@1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/eip1559-fee-suggestions-ethers/-/eip1559-fee-suggestions-ethers-1.3.3.tgz#cf21b6ae4734b697c8f79e556d91aeda3e464d60" + integrity sha512-W/5SQICRpDL0XvOdcX5oVWfaE2sow2u9il8I6Qyd9fkL9XY1knypywTcoBTdU9ULrPoP3phn/RnEKGq7Y8qkLw== + dependencies: + "@ethersproject/providers" "^5.5.0" + bignumber.js "^9.0.1" + ethers "^5.4.2" + moving-averages "^4.0.6" + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enabled@2.0.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== + +es6-object-assign@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" + integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.1.tgz#936821d3462675f25a18ac5fd88a67cc15b393bd" + integrity sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint@8.30.0: + version "8.30.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" + integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ== + dependencies: + "@eslint/eslintrc" "^1.4.0" + "@humanwhocodes/config-array" "^0.11.8" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.4.0" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-sdsl "^4.1.4" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.4.0: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +ethers@5.7.2, ethers@^5.4.2, ethers@^5.7.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.3.0" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" + integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fecha@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +fn.name@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3: + 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.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-callable@^1.1.3: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-nan@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typed-array@^1.1.10, is-typed-array@^1.1.3: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +js-sdsl@^4.1.4: + version "4.4.1" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.1.tgz#9e3c7b566d8d9a7e1fe8fc26d00b5ab0f8918ab3" + integrity sha512-6Gsx8R0RucyePbWqPssR8DyfuXmLBooYN5cZFZKjHGnQuaf7pEzhtpceagJxVu4LqhYY5EYA7nko3FmeHZ1KbA== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +jszip@^3.2.2: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + +kuler@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +logform@^2.3.2, logform@^2.4.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b" + integrity sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg== + dependencies: + "@colors/colors" "1.5.0" + "@types/triple-beam" "^1.3.2" + fecha "^4.2.0" + ms "^2.1.1" + safe-stable-stringify "^2.3.1" + triple-beam "^1.3.0" + +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +mocha@10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +moment-timezone@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.3.tgz#34ba53bd719677975bee9d0e8ba799ad9373f082" + integrity sha512-CruicnN/CSlOKDfyI+lQXZru32gIRGX1wF5PgW3sImRpAwo+kj/XkDVQ4shkU/GOcpigZUsJjOcBpuIZAqaROA== + dependencies: + moment ">= 2.6.0" + +"moment@>= 2.6.0", moment@>=2.14.0: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + +moving-averages@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/moving-averages/-/moving-averages-4.0.6.tgz#4978d4d9f68aef8f2b5fa028b1ec316da0cc8c95" + integrity sha512-Jv+mH0emTFP40Q5ONsBqTfIO9NuUyK9zuW4pWbOzWJm8jEqpLBtAH2CnE2MFIuH/G9f9nDugmnDVUJaHx9jckw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +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.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +nconf@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/nconf/-/nconf-0.12.0.tgz#9cf70757aae4d440d43ed53c42f87da18471b8bf" + integrity sha512-T3fZPw3c7Dfrz8JBQEbEcZJ2s8f7cUMpKuyBtsGQe0b71pcXx6gNh4oti2xh5dxB+gO9ufNfISBlGvvWtfyMcA== + dependencies: + async "^3.0.0" + ini "^2.0.0" + secure-keys "^1.0.0" + yargs "^16.1.1" + +nodemon@2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.20.tgz#e3537de768a492e8d74da5c5813cb0c7486fc701" + integrity sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw== + dependencies: + chokidar "^3.5.2" + debug "^3.2.7" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^5.7.1" + simple-update-notifier "^1.0.7" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +one-time@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== + dependencies: + fn.name "1.x.x" + +optionator@^0.9.1: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +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" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@3.0.2, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-stable-stringify@^2.3.1: + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secure-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/secure-keys/-/secure-keys-1.0.0.tgz#f0c82d98a3b139a8776a8808050b824431087fca" + integrity sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg== + +semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^7.3.7: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +semver@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + +simple-update-notifier@^1.0.7: + version "1.1.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" + integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== + dependencies: + semver "~7.0.0" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" + +triple-beam@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" + integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== + +tsc@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/tsc/-/tsc-2.0.4.tgz#5f6499146abea5dca4420b451fa4f2f9345238f5" + integrity sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typescript@4.8.4: + version "4.8.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" + integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== + +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@^0.12.0: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +which-typed-array@^1.1.2: + version "1.1.10" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.10.tgz#74baa2789991905c2076abb317103b866c64e69e" + integrity sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +winston-transport@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" + integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== + dependencies: + logform "^2.3.2" + readable-stream "^3.6.0" + triple-beam "^1.3.0" + +winston@*: + version "3.10.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.10.0.tgz#d033cb7bd3ced026fed13bf9d92c55b903116803" + integrity sha512-nT6SIDaE9B7ZRO0u3UvdrimG0HkB7dSTAgInQnNR2SOPJ4bvq5q79+pXLftKmP52lJGW15+H5MCK0nM9D3KB/g== + dependencies: + "@colors/colors" "1.5.0" + "@dabh/diagnostics" "^2.0.2" + async "^3.2.3" + is-stream "^2.0.0" + logform "^2.4.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.5.0" + +winston@3.8.2: + version "3.8.2" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.8.2.tgz#56e16b34022eb4cff2638196d9646d7430fdad50" + integrity sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew== + dependencies: + "@colors/colors" "1.5.0" + "@dabh/diagnostics" "^2.0.2" + async "^3.2.3" + is-stream "^2.0.0" + logform "^2.4.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.5.0" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0, yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zip-dir@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/zip-dir/-/zip-dir-2.0.0.tgz#c5df6e15c8f9efeb4e320377028c9f5c8277c932" + integrity sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg== + dependencies: + async "^3.2.0" + jszip "^3.2.2" From cb3dce5a46592e85a9bef36c9f5c86416fc92949 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 16 Jul 2023 18:39:00 +0700 Subject: [PATCH 019/173] change deploy script for production --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 943cbfc..a9205f7 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "author": "Cengiz Dincoglu", "scripts": { "marketMaker-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji", - "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=development" + "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=production" }, "dependencies": { "@ethersproject/experimental": "5.7.0", From 8c7d6206a36e0c5d6e4ae6db167f331cd04ac10b Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 16 Jul 2023 18:47:00 +0700 Subject: [PATCH 020/173] changed interval to 15 seconds from accidental 150 seconds --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 58f9306..afedd6d 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -44,7 +44,7 @@ class MarketMakerBot extends AbstractBot { if (initializing) { await this.getNewMarketPrice(); - this.interval = 150000; //Min 10 seconds + this.interval = 15000; //Min 10 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); From 5f5856c0a8808e4f42a94fd80c21a0d82c140020 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 16 Jul 2023 22:18:05 +0700 Subject: [PATCH 021/173] fixed timestamps. Should be updating orders in memory correctly now --- services/bots/AbstractBot.ts | 20 +++++++++----------- services/bots/MarketMakerBot.ts | 8 +++----- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 196717a..8b5ae3d 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -445,7 +445,7 @@ abstract class AbstractBot { 0, 0, newOrders[i].level, - new Date().getSeconds() + Date.now() ); this.addOrderToMap(order); @@ -625,7 +625,7 @@ abstract class AbstractBot { 0, 0, level, - new Date().getSeconds() + Date.now() ); this.addOrderToMap(order); @@ -977,7 +977,7 @@ abstract class AbstractBot { gasPrice: utils.formatUnits(gasPrice, 9), cumulativeGasUsed, level, - timestamp: new Date().getSeconds() + timestamp: Date.now() }); } @@ -1028,7 +1028,7 @@ abstract class AbstractBot { tx.effectiveGasPrice ? tx.effectiveGasPrice.toString() : "225", tx.cumulativeGasUsed.toString(), level, - new Date().getSeconds() + Date.now() ); if (utils.statusMap[order.status] === "NEW" || utils.statusMap[order.status] === "PARTIAL") { @@ -1417,9 +1417,7 @@ abstract class AbstractBot { totalfee: new BigNumber(order.totalfee), gasUsed: 0, gasPrice: 0, - cumulativeGasUsed: 0, - level: -1, - timestamp: new Date().getSeconds() + cumulativeGasUsed: 0 }); this.addOrderToMap(orderfromDb); @@ -1436,9 +1434,9 @@ abstract class AbstractBot { async checkOrdersInChain() { const promises: any = []; const orders: any = []; - const time = new Date().getSeconds(); + const time = Date.now() for (const order of this.orders.values()) { - if (time - order.timestamp > this.interval){ // If the order hasn't been updated within the interval time, check the chain to make sure we're not missing any information about it. + if ((time - order.timestamp)/1000 > this.interval/2 || !order.timestamp){ // If the order hasn't been updated within the interval time, check the chain to make sure we're not missing any information about it. orders.push(order); promises.push(this.tradePair.getOrder(order.id)); } @@ -1479,8 +1477,8 @@ abstract class AbstractBot { "0", "0", "0", - 0, - new Date().getSeconds() + orderinMemory.level, + orderinMemory.timestamp ); //tx, blocknbr , gasUsed, gasPrice, cumulativeGasUsed) ; const ordstatus = orderInChain.status; diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index afedd6d..1633e73 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -114,7 +114,7 @@ class MarketMakerBot extends AbstractBot { let duplicates: any[] = []; this.orders.forEach((e,i)=>{ - if (e.side === 0){ + if (e.side === 0 && typeof e.level != undefined){ let skip = false; for (let i = 0;i 0){ @@ -148,8 +148,6 @@ class MarketMakerBot extends AbstractBot { let bidsSorted = sortOrders(bids, "price", "descending"); let asksSorted = sortOrders(asks, "price", "ascending"); - console.log(bidsSorted); - console.log(asksSorted); // If there will be overlapping orders, wait for the orders of the side in which the price moved to be replaced first, then follow with the others. if (myBestAsk && startingBidPrice > myBestAsk){ From 31baad8869f99fd365d4bd19985c78ba7133fb43 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 16 Jul 2023 22:48:52 +0700 Subject: [PATCH 022/173] check for level!=-1 and add logic for custom rpc if using production --- services/bots/AbstractBot.ts | 15 +++++++++++---- services/bots/MarketMakerBot.ts | 4 ++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 8b5ae3d..1afe6fb 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -198,10 +198,17 @@ abstract class AbstractBot { await this.getTokenDetails(); this.contracts["MainnetProvider"] = { provider: this.getProvider(this.getEnvironment("mainnet").chain_instance), nonce: 0 }; - this.contracts["SubNetProvider"] = { - provider: this.getProvider(this.getEnvironment("subnet").chain_instance, this.ratelimit_token), - nonce: 0 - }; + if (getConfig("NODE_ENV_SETTINGS") == "production"){ + this.contracts["SubNetProvider"] = { + provider: this.getProvider(getConfig("rpc_url"), this.ratelimit_token), + nonce: 0 + }; + } else { + this.contracts["SubNetProvider"] = { + provider: this.getProvider(this.getEnvironment("subnet").chain_instance, this.ratelimit_token), + nonce: 0 + }; + } this.contracts["MainnetWallet"] = new NonceManager(new ethers.Wallet(this.privateKey, this.contracts["MainnetProvider"].provider)); const wal = new ethers.Wallet(this.privateKey, this.contracts["SubNetProvider"].provider); diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 1633e73..6ec086e 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -114,7 +114,7 @@ class MarketMakerBot extends AbstractBot { let duplicates: any[] = []; this.orders.forEach((e,i)=>{ - if (e.side === 0 && typeof e.level != undefined){ + if (e.side === 0 && e.level != undefined && e.level != -1){ let skip = false; for (let i = 0;i Date: Mon, 17 Jul 2023 16:45:24 +0700 Subject: [PATCH 023/173] get best orders from live orderbook --- services/bots/AbstractBot.ts | 21 +++++++++++++++++++++ services/bots/MarketMakerBot.ts | 20 +++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 1afe6fb..87ceb5d 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -62,6 +62,11 @@ abstract class AbstractBot { protected tokenDetails: any; protected signature: any; protected axiosConfig: any; + protected orderBooks: any; + protected orderBookID: any; + protected orderBookID1: any; + protected currentBestBid: any; + protected currentBestAsk: any; constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { this.logger = getLogger("Bot"); @@ -110,6 +115,7 @@ abstract class AbstractBot { async getDeployments() { await this.getDeployment(BlockchainContractType.Portfolio); await this.getDeployment(BlockchainContractType.TradePairs); + await this.getDeployment(BlockchainContractType.OrderBooks); this.contracts["AVAX"] = { contractName: "AVAX", inByte32: utils.fromUtf8("AVAX"), @@ -244,6 +250,13 @@ abstract class AbstractBot { this.tradePair = new ethers.Contract(deployment.address, deployment.abi.abi, this.contracts["SubnetWallet"]); this.contracts["TradePairs"].deployedContract = this.tradePair; + + deployment = this.contracts["OrderBooks"]; + this.orderBooks = new ethers.Contract(deployment.address, deployment.abi.abi, this.contracts["SubnetWallet"]); + this.orderBookID = await this.tradePair.getBookId(this.tradePairByte32,0); + this.orderBookID1 = await this.tradePair.getBookId(this.tradePairByte32,1); + await this.getBestOrders(); + this.minTradeAmnt = this.pairObject.mintrade_amnt; this.maxTradeAmnt = this.pairObject.maxtrade_amnt; this.quoteDisplayDecimals = this.pairObject.quotedisplaydecimals; @@ -1891,6 +1904,14 @@ abstract class AbstractBot { } } + async getBestOrders(){ + const currentBestBid = await this.orderBooks.getTopOfTheBook(this.orderBookID); + const currentBestAsk = await this.orderBooks.getTopOfTheBook(this.orderBookID1); + this.currentBestBid = currentBestBid.price.toNumber()/1000000; + this.currentBestAsk = currentBestAsk.price.toNumber()/1000000; + return [this.currentBestBid,this.currentBestAsk]; + } + async cleanUpAndExit() { if (!this.cleanupCalled) { const timeout = 10; //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 6ec086e..c6f9da0 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -20,6 +20,8 @@ class MarketMakerBot extends AbstractBot { protected refreshOrderTolerance: any; protected flatAmount: any; protected timer: any; + // protected bestAsk: any; + // protected bestBid: any; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -43,6 +45,7 @@ class MarketMakerBot extends AbstractBot { const initializing = await super.initialize(); if (initializing) { await this.getNewMarketPrice(); + // await this.getBestOrders(); this.interval = 15000; //Min 10 seconds @@ -106,8 +109,8 @@ class MarketMakerBot extends AbstractBot { console.log("000000000000000 COUNTER:",this.counter); let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); - const myBestAsk = this.orderbook.bestask() ? this.orderbook.bestask().price.toNumber() : undefined; - const myBestBid = this.orderbook.bestbid() ? this.orderbook.bestbid().price.toNumber() : undefined; + const myBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; + const myBestBid = this.currentBestBid ? this.currentBestBid : undefined; let bids: any[] = []; let asks: any[] = []; @@ -154,15 +157,13 @@ class MarketMakerBot extends AbstractBot { console.log("BEST ASK: ",myBestAsk, "STARTING BID PRICE: ", startingBidPrice) startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread); - await this.replaceAsks(asksSorted, startingAskPrice); - await this.replaceBids(bidsSorted, startingBidPrice); + Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); } else if (myBestBid && startingAskPrice < myBestBid){ console.log("BEST BID: ",myBestBid, "STARTING ASK PRICE: ", startingAskPrice) startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread); - await this.replaceBids(bidsSorted, startingBidPrice); - await this.replaceAsks(asksSorted, startingAskPrice); + Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); } else { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); @@ -176,7 +177,7 @@ class MarketMakerBot extends AbstractBot { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ if (this.status){ - await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice(),this.correctNonce(this.contracts["SubNetProvider"])]); + await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice(),this.correctNonce(this.contracts["SubNetProvider"]),this.getBestOrders()]); this.timer = 2000; this.updateOrders(); } @@ -368,6 +369,11 @@ class MarketMakerBot extends AbstractBot { } } + // async getBestOrders(){ + // this.bestBid = getBottomOfTheBook + // this.bestAsk = getTopOfTheBook + // } + } const sortOrders = (arr: any, propertyName: any, order: string = 'ascending') => { From c209604a9e4007bac7a9d83bd324ca705a3f2889 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 17:03:11 +0700 Subject: [PATCH 024/173] add default urls for production --- config/default.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/default.json b/config/default.json index deaa69b..0c69bba 100644 --- a/config/default.json +++ b/config/default.json @@ -1,3 +1,5 @@ { - + "API_URL" : "https://api.dexalot.com/", + "DOMAIN_LINK" : "https://api.dexalot.com/", + "ORIGIN_LINK": "https://api.dexalot.com/" } From 62958f2584d393bf4b46feaf96b41d8cd43f83e2 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 17:43:49 +0700 Subject: [PATCH 025/173] increase gas price to +15% from +5% --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 87ceb5d..225abaa 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -770,7 +770,7 @@ abstract class AbstractBot { async getOptions(provider: any = this.contracts["SubNetProvider"], gasEstimate: BigNumberEthers = BigNumberEthers.from(700000)) { const gasPx = await this.getGasPrice(provider); - const maxFeePerGas = Math.ceil(gasPx.mul(105).div(100).toNumber()); + const maxFeePerGas = Math.ceil(gasPx.mul(115).div(100).toNumber()); const gasLimit = Math.min(gasEstimate.mul(102).div(100).toNumber(), 30000000); // Block Gas Limit 30M const optionsWithNonce = { gasLimit, maxFeePerGas, maxPriorityFeePerGas: 1, nonce: 0 }; From 4952ccf9154c6cc770aca60f18e661df9d931451 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 17:55:37 +0700 Subject: [PATCH 026/173] add leniancy in order qty --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index c6f9da0..9278c78 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -297,14 +297,14 @@ class MarketMakerBot extends AbstractBot { getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds){ + if (this.getLevelQty(level) < availableFunds * .975){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 1.025){ return availableFunds*.975; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds){ + if (this.getLevelQty(level) < availableFunds * .975){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 1.025){ return availableFunds * .975; From addf83e242fb27cebc8f52395abefb4847da67e3 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 18:14:33 +0700 Subject: [PATCH 027/173] add delay for avax/usdt pair to avoid nonce conflicts with avax/usdc --- services/bots/MarketMakerBot.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9278c78..b679602 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -107,6 +107,12 @@ class MarketMakerBot extends AbstractBot { this.counter ++; this.timer = this.interval; console.log("000000000000000 COUNTER:",this.counter); + + // having issues with nonces when avax/usdc and avax/usdt send orders at the same time. This gives priority to avaxusdc + if (this.tradePairIdentifier == "AVAX/USDt"){ + await utils.sleep(500); + } + await this.correctNonce(this.contracts["SubNetProvider"]); let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); const myBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; @@ -177,7 +183,7 @@ class MarketMakerBot extends AbstractBot { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ if (this.status){ - await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice(),this.correctNonce(this.contracts["SubNetProvider"]),this.getBestOrders()]); + await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice(),this.getBestOrders()]); this.timer = 2000; this.updateOrders(); } From 89d35664fa976236f62b17f2b36ab1ecc047d5aa Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 21:56:34 +0700 Subject: [PATCH 028/173] replace portfoliotot with portfoliototavail. :( --- services/bots/MarketMakerBot.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index b679602..eb89366 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -205,9 +205,9 @@ class MarketMakerBot extends AbstractBot { for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ let bidPrice = new BigNumber(initialBidPrice * (1-this.getSpread(levels[x][1]-1))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioTot - (bidsEnroute * bidPrice.toNumber()))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioAvail - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioTot); + console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioAvail); bidsEnroute += bidQty.toNumber(); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } else { @@ -216,9 +216,9 @@ class MarketMakerBot extends AbstractBot { } else { //--------------- SET ASKS --------------- // let askPrice = new BigNumber(initialAskPrice * (1+this.getSpread(levels[x][1]-1))); - let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioTot - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioAvail - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioTot); + console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioAvail); asksEnRoute += askQty.toNumber(); newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); } else { @@ -254,13 +254,13 @@ class MarketMakerBot extends AbstractBot { } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ let bidPrice = new BigNumber(startingBidPrice * (1-this.getSpread(i))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioTot + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioAvail + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); this.cancelReplaceOrder(order,bidPrice,bidQty); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioAvail, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); } } else { console.log("MAKE FRESH ORDER:", order.id,order.status); @@ -283,13 +283,13 @@ class MarketMakerBot extends AbstractBot { } if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ let askPrice = new BigNumber(startingAskPrice * (1+this.getSpread(i))); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioTot + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioAvail + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); console.log("REPLACE ORDER:",askPrice,askQty, i+1); this.cancelReplaceOrder(order,askPrice,askQty); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioTot, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); + console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioAvail, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); } } else { console.log("MAKE FRESH ORDER"); From 7b028abbfe32ca9f4bdad78f33a4adb4ca280322 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 22:07:49 +0700 Subject: [PATCH 029/173] fixed getqty calculations --- services/bots/MarketMakerBot.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index eb89366..2ba164e 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -302,17 +302,17 @@ class MarketMakerBot extends AbstractBot { // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ - console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds * .975){ + // console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + if (this.getLevelQty(level) < availableFunds/price.toNumber() * .975){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 1.025){ - return availableFunds*.975; + return availableFunds/price.toNumber() *.975; } else { return 0;} } else if (side === 1) { - console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + // console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .975){ return this.getLevelQty(level); - } else if (availableFunds > this.minTradeAmnt * 1.025){ + } else if (availableFunds * .975 > this.minTradeAmnt * 1.025){ return availableFunds * .975; } else {return 0;} } else { From 140a173eef3255f22595e6d6ec1173a247dc5eaf Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 23:15:08 +0700 Subject: [PATCH 030/173] add nonce tracker --- .gitignore | 1 + services/bots/AbstractBot.ts | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/.gitignore b/.gitignore index f489202..ceb32c2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ Procfile .env.* package-lock.json /logs-* +/services/bots/nonce.json \ No newline at end of file diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 225abaa..4195d8f 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -7,6 +7,7 @@ import { BlockchainContractType } from "../../models/BlockchainContractType"; import { BigNumber } from "bignumber.js"; import { BigNumber as BigNumberEthers } from "ethers"; import axios from "axios"; +import fs from "fs"; import { getLogger } from "../logger"; import OrderBook from "./orderbook"; import NewOrder from "./classes"; @@ -476,6 +477,7 @@ abstract class AbstractBot { const gasest = await this.getAddOrderListGasEstimate(clientOrderIds, prices, quantities, sides, type2s); this.logger.warn(`${this.instanceName} Gas Est ${gasest.toString()}`); + await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.addLimitOrderList( this.tradePairByte32, clientOrderIds, @@ -650,6 +652,8 @@ abstract class AbstractBot { this.addOrderToMap(order); + await this.getLatestNonce(this.contracts["SubNetProvider"]); + const tx = await this.tradePair.addOrder( order.traderaddress, order.clientOrderId, @@ -850,11 +854,27 @@ abstract class AbstractBot { try { const expectedNonce = await provider.provider.getTransactionCount(this.account); provider.nonce = expectedNonce; + fs.writeFile('./services/bots/nonce.json', JSON.stringify({nonce:provider.nonce}), (err) => { + if (err) throw err; + }); } catch (error) { this.logger.error(`${this.instanceName} 'Error during nonce correction`, error); } } + async getLatestNonce (provider: any) { + return fs.readFile('./services/bots/nonce.json', (err, data) => { + if (err) throw err; + provider.nonce = JSON.parse(data.toString()).nonce; + console.log("NONCE:", provider.nonce); + return fs.writeFile('./services/bots/nonce.json', JSON.stringify({nonce:provider.nonce + 1}), (err) => { + if (err) throw err; + return true; + }); + }); + + } + async getWalletBalance(tokenDetails: any, provider: any, envType = "subnet") { let balance; if (this.isNative(tokenDetails.symbol, envType)) { @@ -1174,6 +1194,7 @@ abstract class AbstractBot { this.orderCount++; this.logger.warn(`${this.instanceName} Cancelling all outstanding orders, OrderNbr ${this.orderCount}`); const gasest = await this.getCancelAllOrdersGasEstimate(orderIds); + await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.cancelOrderList(orderIds, await this.getOptions(this.contracts["SubNetProvider"], gasest)); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); @@ -1237,6 +1258,7 @@ abstract class AbstractBot { } ::: ${order.quantity.toString()} ${this.base} @ ${order.price.toString()} ${this.quote}` ); const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); + await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.cancelOrder(order.id, options); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); //const orderLog = await this.race({ promise: tx.wait(), count: this.orderCount} ); @@ -1341,6 +1363,7 @@ abstract class AbstractBot { } ::: ${quantity.toString()} ${this.base} @ ${price.toString()} ${this.quote}` ); const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1500000)); + await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.cancelReplaceOrder(order.id, clientOrderId, priceToSend, quantityToSend, options); const orderLog = await tx.wait(); From 3df02c781a8c1040e771799819d05ffb11e2c0f2 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 17 Jul 2023 23:52:10 +0700 Subject: [PATCH 031/173] fixed pathing to absolute pathing for nonce tracker --- services/bots/AbstractBot.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 4195d8f..4e451cb 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -8,6 +8,7 @@ import { BigNumber } from "bignumber.js"; import { BigNumber as BigNumberEthers } from "ethers"; import axios from "axios"; import fs from "fs"; +import path from "path"; import { getLogger } from "../logger"; import OrderBook from "./orderbook"; import NewOrder from "./classes"; @@ -851,10 +852,11 @@ abstract class AbstractBot { } async correctNonce(provider: any) { + let filePath = path.join(__dirname, './nonce.json'); try { const expectedNonce = await provider.provider.getTransactionCount(this.account); provider.nonce = expectedNonce; - fs.writeFile('./services/bots/nonce.json', JSON.stringify({nonce:provider.nonce}), (err) => { + fs.writeFile(filePath, JSON.stringify({nonce:provider.nonce}), (err) => { if (err) throw err; }); } catch (error) { @@ -863,11 +865,12 @@ abstract class AbstractBot { } async getLatestNonce (provider: any) { - return fs.readFile('./services/bots/nonce.json', (err, data) => { + let filePath = path.join(__dirname, './nonce.json'); + return fs.readFile(filePath, (err, data) => { if (err) throw err; provider.nonce = JSON.parse(data.toString()).nonce; console.log("NONCE:", provider.nonce); - return fs.writeFile('./services/bots/nonce.json', JSON.stringify({nonce:provider.nonce + 1}), (err) => { + return fs.writeFile(filePath, JSON.stringify({nonce:provider.nonce + 1}), (err) => { if (err) throw err; return true; }); From 43b25847638486a86b80478a1065aef2095c7fbd Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 01:11:08 +0700 Subject: [PATCH 032/173] removed nonce tracker, wasn't working. fixed best bid and best ask. --- services/bots/AbstractBot.ts | 35 ++++++++------------------------- services/bots/MarketMakerBot.ts | 16 ++++++++++----- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 4e451cb..122db9a 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -355,7 +355,8 @@ abstract class AbstractBot { if (this.orderUpdater !== undefined) { clearTimeout(this.orderUpdater); } - this.cancelOrderList([], 100) + setTimeout(()=> { + this.cancelOrderList([], 100) .then(() => { this.logger.warn(`${this.instanceName} Waiting 5 seconds before removing order listeners"...`); setTimeout(async () => { @@ -376,6 +377,7 @@ abstract class AbstractBot { .catch((e: any) => { this.logger.error(`${this.instanceName} problem in Bot Stop + ${e.message}`); }); + },5000); } getSettingValue(settingname: string) { @@ -478,7 +480,6 @@ abstract class AbstractBot { const gasest = await this.getAddOrderListGasEstimate(clientOrderIds, prices, quantities, sides, type2s); this.logger.warn(`${this.instanceName} Gas Est ${gasest.toString()}`); - await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.addLimitOrderList( this.tradePairByte32, clientOrderIds, @@ -653,8 +654,6 @@ abstract class AbstractBot { this.addOrderToMap(order); - await this.getLatestNonce(this.contracts["SubNetProvider"]); - const tx = await this.tradePair.addOrder( order.traderaddress, order.clientOrderId, @@ -856,28 +855,11 @@ abstract class AbstractBot { try { const expectedNonce = await provider.provider.getTransactionCount(this.account); provider.nonce = expectedNonce; - fs.writeFile(filePath, JSON.stringify({nonce:provider.nonce}), (err) => { - if (err) throw err; - }); } catch (error) { this.logger.error(`${this.instanceName} 'Error during nonce correction`, error); } } - async getLatestNonce (provider: any) { - let filePath = path.join(__dirname, './nonce.json'); - return fs.readFile(filePath, (err, data) => { - if (err) throw err; - provider.nonce = JSON.parse(data.toString()).nonce; - console.log("NONCE:", provider.nonce); - return fs.writeFile(filePath, JSON.stringify({nonce:provider.nonce + 1}), (err) => { - if (err) throw err; - return true; - }); - }); - - } - async getWalletBalance(tokenDetails: any, provider: any, envType = "subnet") { let balance; if (this.isNative(tokenDetails.symbol, envType)) { @@ -1197,7 +1179,6 @@ abstract class AbstractBot { this.orderCount++; this.logger.warn(`${this.instanceName} Cancelling all outstanding orders, OrderNbr ${this.orderCount}`); const gasest = await this.getCancelAllOrdersGasEstimate(orderIds); - await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.cancelOrderList(orderIds, await this.getOptions(this.contracts["SubNetProvider"], gasest)); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); @@ -1261,7 +1242,6 @@ abstract class AbstractBot { } ::: ${order.quantity.toString()} ${this.base} @ ${order.price.toString()} ${this.quote}` ); const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); - await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.cancelOrder(order.id, options); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); //const orderLog = await this.race({ promise: tx.wait(), count: this.orderCount} ); @@ -1366,7 +1346,6 @@ abstract class AbstractBot { } ::: ${quantity.toString()} ${this.base} @ ${price.toString()} ${this.quote}` ); const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1500000)); - await this.getLatestNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.cancelReplaceOrder(order.id, clientOrderId, priceToSend, quantityToSend, options); const orderLog = await tx.wait(); @@ -1931,10 +1910,13 @@ abstract class AbstractBot { } async getBestOrders(){ - const currentBestBid = await this.orderBooks.getTopOfTheBook(this.orderBookID); - const currentBestAsk = await this.orderBooks.getTopOfTheBook(this.orderBookID1); + const currentBestBid = await this.orderBooks.getTopOfTheBook(this.orderBookID1); + const currentBestAsk = await this.orderBooks.getTopOfTheBook(this.orderBookID); this.currentBestBid = currentBestBid.price.toNumber()/1000000; this.currentBestAsk = currentBestAsk.price.toNumber()/1000000; + console.log(this.currentBestAsk); + console.log(this.currentBestBid); + return [this.currentBestBid,this.currentBestAsk]; } @@ -1943,7 +1925,6 @@ abstract class AbstractBot { const timeout = 10; //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds this.logger.warn(`${this.instanceName} === Process Exit Called === `); this.cleanupCalled = true; - await utils.sleep(10000); this.logger.warn(`${this.instanceName} === STOPPING === `); await this.stop(); diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 2ba164e..4a683f1 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -152,7 +152,13 @@ class MarketMakerBot extends AbstractBot { } }); if (duplicates.length > 0){ - this.cancelOrderList(duplicates); + let toCancel = []; + for (let i = 0; i < duplicates.length; i++){ + if (duplicates[i]){ + toCancel.push(duplicates[i]); + } + } + this.cancelOrderList(toCancel); } let bidsSorted = sortOrders(bids, "price", "descending"); @@ -163,13 +169,13 @@ class MarketMakerBot extends AbstractBot { console.log("BEST ASK: ",myBestAsk, "STARTING BID PRICE: ", startingBidPrice) startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread); - Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); } else if (myBestBid && startingAskPrice < myBestBid){ console.log("BEST BID: ",myBestBid, "STARTING ASK PRICE: ", startingAskPrice) startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread); - Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); } else { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); @@ -232,11 +238,11 @@ class MarketMakerBot extends AbstractBot { console.log("ERROR - NewOrderList empty"); } else if (newOrderList.length == 1){ if (this.status){ - await this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); + this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); } } else { if (this.status){ - await this.addLimitOrderList(newOrderList); + this.addLimitOrderList(newOrderList); } } } From 9583b3d90676445c871422ee2d945a58b3dfba02 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 01:19:39 +0700 Subject: [PATCH 033/173] fixed currentbestorders --- services/bots/AbstractBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 122db9a..ddfa482 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1910,8 +1910,8 @@ abstract class AbstractBot { } async getBestOrders(){ - const currentBestBid = await this.orderBooks.getTopOfTheBook(this.orderBookID1); - const currentBestAsk = await this.orderBooks.getTopOfTheBook(this.orderBookID); + const currentBestBid = await this.orderBooks.getTopOfTheBook(this.orderBookID); + const currentBestAsk = await this.orderBooks.getTopOfTheBook(this.orderBookID1); this.currentBestBid = currentBestBid.price.toNumber()/1000000; this.currentBestAsk = currentBestAsk.price.toNumber()/1000000; console.log(this.currentBestAsk); From d26d40aa0c69a7e128490f71006272231e691dbf Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 12:00:07 +0700 Subject: [PATCH 034/173] retry if failed cancel/replace or cancelOrderList --- services/bots/AbstractBot.ts | 41 ++++++++++++++++++++------------- services/bots/MarketMakerBot.ts | 6 ++--- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index ddfa482..32fb3d1 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -911,21 +911,21 @@ abstract class AbstractBot { utils.printBalances(this.account, "ALOT", this.contracts["ALOT"]); - if (this.contracts["ALOT"].subnetBal <= this.getSettingValue("LOW_AVAX_CHAIN_BALANCE")) { - let text = "*****************" + this.instanceName + " LOW AVAX Chain Balance for account :" + this.account; - text = text + utils.lineBreak + "*****************************************************************************************"; - text = - text + - utils.lineBreak + - "LOW AVAX Chain Balance, you will not be able pay for gas fees soon unless you replenish your account. Current Balance: " + - this.contracts["ALOT"].subnetBal; - text = - text + - utils.lineBreak + - "*****************************************************************************************" + - utils.lineBreak; - this.logger.warn(`${text}`); - } + // if (this.contracts["ALOT"].subnetBal <= this.getSettingValue("LOW_AVAX_CHAIN_BALANCE")) { + // let text = "*****************" + this.instanceName + " LOW AVAX Chain Balance for account :" + this.account; + // text = text + utils.lineBreak + "*****************************************************************************************"; + // text = + // text + + // utils.lineBreak + + // "LOW AVAX Chain Balance, you will not be able pay for gas fees soon unless you replenish your account. Current Balance: " + + // this.contracts["ALOT"].subnetBal; + // text = + // text + + // utils.lineBreak + + // "*****************************************************************************************" + + // utils.lineBreak; + // this.logger.warn(`${text}`); + // } //Chain Base wallet if (this.base !== "AVAX" && this.base !== "ALOT") { @@ -1217,6 +1217,8 @@ abstract class AbstractBot { } } catch (error) { this.logger.error(`${this.instanceName} Error during CancelAll`, error); + await this.correctNonce(this.contracts["SubNetProvider"]); + this.cancelOrderList(); } } @@ -1311,10 +1313,14 @@ abstract class AbstractBot { } } - async cancelReplaceOrder(order: any, price: BigNumber, quantity: BigNumber) { + async cancelReplaceOrder(order: any, price: BigNumber, quantity: BigNumber, tries: number = 0) { if (!this.status) { return; } + if (tries > 2){ + this.cancelOrder(order.id); + return + } try { this.checkWashTrade(order.side, price); @@ -1389,6 +1395,7 @@ abstract class AbstractBot { )} @ ${price.toFixed(this.quoteDisplayDecimals)} Invalid Nonce` ); await this.correctNonce(this.contracts["SubNetProvider"]); + this.cancelReplaceOrder(order,price,quantity, tries +1); } else { const reason = await this.getRevertReason(error); if (reason) { @@ -1397,6 +1404,7 @@ abstract class AbstractBot { this.baseDisplayDecimals )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` ); + this.cancelReplaceOrder(order,price,quantity, tries +1); } else { this.logger.error( `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( @@ -1404,6 +1412,7 @@ abstract class AbstractBot { )} @ ${price.toFixed(this.quoteDisplayDecimals)}`, error ); + this.cancelReplaceOrder(order,price,quantity, tries +1); } } return false; diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 4a683f1..cd92189 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -213,7 +213,7 @@ class MarketMakerBot extends AbstractBot { let bidPrice = new BigNumber(initialBidPrice * (1-this.getSpread(levels[x][1]-1))); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioAvail - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Tot: ",this.contracts[this.quote].portfolioAvail); + console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Avail: ",this.contracts[this.quote].portfolioAvail); bidsEnroute += bidQty.toNumber(); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } else { @@ -224,7 +224,7 @@ class MarketMakerBot extends AbstractBot { let askPrice = new BigNumber(initialAskPrice * (1+this.getSpread(levels[x][1]-1))); let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioAvail - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Tot: ",this.contracts[this.base].portfolioAvail); + console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",this.contracts[this.base].portfolioAvail); asksEnRoute += askQty.toNumber(); newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); } else { @@ -311,7 +311,7 @@ class MarketMakerBot extends AbstractBot { // console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds/price.toNumber() * .975){ return this.getLevelQty(level); - } else if (availableFunds > this.minTradeAmnt * 1.025){ + } else if (availableFunds/price.toNumber() *.975 > this.minTradeAmnt * 1.025){ return availableFunds/price.toNumber() *.975; } else { return 0;} } else if (side === 1) { From 54135c37646a29ad79acc590adf2572c3a38c56e Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 14:14:25 +0700 Subject: [PATCH 035/173] removed timestamp, as it wasn't really helping. removed some unecessary code in order sorting --- services/bots/AbstractBot.ts | 69 ++++++++++++++++----------------- services/bots/MarketMakerBot.ts | 37 ++++++++++-------- 2 files changed, 54 insertions(+), 52 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 32fb3d1..456d99f 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -372,7 +372,7 @@ abstract class AbstractBot { this.filter = undefined; this.logger.warn(`${this.instanceName} Removed order listeners`); } - }, 5000); + }, 3000); }) .catch((e: any) => { this.logger.error(`${this.instanceName} problem in Bot Stop + ${e.message}`); @@ -468,8 +468,7 @@ abstract class AbstractBot { 0, 0, 0, - newOrders[i].level, - Date.now() + newOrders[i].level ); this.addOrderToMap(order); @@ -648,8 +647,7 @@ abstract class AbstractBot { 0, 0, 0, - level, - Date.now() + level ); this.addOrderToMap(order); @@ -775,7 +773,7 @@ abstract class AbstractBot { async getOptions(provider: any = this.contracts["SubNetProvider"], gasEstimate: BigNumberEthers = BigNumberEthers.from(700000)) { const gasPx = await this.getGasPrice(provider); const maxFeePerGas = Math.ceil(gasPx.mul(115).div(100).toNumber()); - const gasLimit = Math.min(gasEstimate.mul(102).div(100).toNumber(), 30000000); // Block Gas Limit 30M + const gasLimit = Math.min(gasEstimate.mul(115).div(100).toNumber(), 30000000); // Block Gas Limit 30M const optionsWithNonce = { gasLimit, maxFeePerGas, maxPriorityFeePerGas: 1, nonce: 0 }; optionsWithNonce.nonce = provider.nonce++; @@ -888,7 +886,7 @@ abstract class AbstractBot { this.contracts["AVAX"].portfolioTot = utils.formatUnits(bal.total, tokenDetails.evmdecimals); this.contracts["AVAX"].portfolioAvail = utils.formatUnits(bal.available, tokenDetails.evmdecimals); - utils.printBalances(this.account, "AVAX", this.contracts["AVAX"]); + //utils.printBalances(this.account, "AVAX", this.contracts["AVAX"]); // if (this.contracts["AVAX"].mainnetBal <= this.getSettingValue('LOW_AVAX_CHAIN_BALANCE') ) { // let text= "*****************" + this.instanceName + " LOW AVAX Chain Balance for account :" + this.account ; @@ -909,7 +907,7 @@ abstract class AbstractBot { this.contracts["ALOT"].portfolioTot = utils.formatUnits(bal.total, tokenDetails.evmdecimals); this.contracts["ALOT"].portfolioAvail = utils.formatUnits(bal.available, tokenDetails.evmdecimals); - utils.printBalances(this.account, "ALOT", this.contracts["ALOT"]); + //utils.printBalances(this.account, "ALOT", this.contracts["ALOT"]); // if (this.contracts["ALOT"].subnetBal <= this.getSettingValue("LOW_AVAX_CHAIN_BALANCE")) { // let text = "*****************" + this.instanceName + " LOW AVAX Chain Balance for account :" + this.account; @@ -937,7 +935,7 @@ abstract class AbstractBot { this.contracts[this.base].portfolioTot = utils.formatUnits(bal.total, tokenDetails.evmdecimals); this.contracts[this.base].portfolioAvail = utils.formatUnits(bal.available, tokenDetails.evmdecimals); - utils.printBalances(this.account, this.base, this.contracts[this.base]); + //utils.printBalances(this.account, this.base, this.contracts[this.base]); } if (this.quote !== "AVAX" && this.quote !== "ALOT") { @@ -949,7 +947,7 @@ abstract class AbstractBot { bal = await portfolio.getBalance(this.account, this.contracts[this.quote].inByte32); //quoteBal this.contracts[this.quote].portfolioTot = utils.formatUnits(bal.total, tokenDetails.evmdecimals); this.contracts[this.quote].portfolioAvail = utils.formatUnits(bal.available, tokenDetails.evmdecimals); - utils.printBalances(this.account, this.quote, this.contracts[this.quote]); + //utils.printBalances(this.account, this.quote, this.contracts[this.quote]); } } catch (error) { this.logger.error(`${this.instanceName} Error during getBalance`, error); @@ -975,8 +973,7 @@ abstract class AbstractBot { gasUsed: any, gasPrice: any, cumulativeGasUsed: any, - level: any, - timestamp: any + level: any ): any { return new Order({ id, @@ -1001,8 +998,7 @@ abstract class AbstractBot { gasUsed, gasPrice: utils.formatUnits(gasPrice, 9), cumulativeGasUsed, - level, - timestamp: Date.now() + level }); } @@ -1052,8 +1048,7 @@ abstract class AbstractBot { tx.gasUsed.toString(), tx.effectiveGasPrice ? tx.effectiveGasPrice.toString() : "225", tx.cumulativeGasUsed.toString(), - level, - Date.now() + level ); if (utils.statusMap[order.status] === "NEW" || utils.statusMap[order.status] === "PARTIAL") { @@ -1160,11 +1155,12 @@ abstract class AbstractBot { async cancelOrderList(orderIds: string[] = [], nbrofOrderstoCancel = 30) { try { + let idsToCancel: string[] = []; if (orderIds.length === 0) { let i = 0; for (const order of this.orders.values()) { if (order.id){ - orderIds.push(order.id); + idsToCancel.push(order.id); } i++; if (i >= nbrofOrderstoCancel) { @@ -1172,14 +1168,21 @@ abstract class AbstractBot { break; } } + } else { + for (let i = 0; i < orderIds.length; i++){ + if (orderIds[i]){ + idsToCancel.push(orderIds[i]); + } + } } //const orderIds = Array.from(this.orders.keys()); - if (orderIds.length > 0) { + if (idsToCancel.length > 0) { this.orderCount++; this.logger.warn(`${this.instanceName} Cancelling all outstanding orders, OrderNbr ${this.orderCount}`); - const gasest = await this.getCancelAllOrdersGasEstimate(orderIds); - const tx = await this.tradePair.cancelOrderList(orderIds, await this.getOptions(this.contracts["SubNetProvider"], gasest)); + const gasest = await this.getCancelAllOrdersGasEstimate(idsToCancel); + await this.correctNonce(this.contracts["SubNetProvider"]); + const tx = await this.tradePair.cancelOrderList(idsToCancel, await this.getOptions(this.contracts["SubNetProvider"], gasest)); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); //const orderLog = await tx.wait(); @@ -1317,8 +1320,8 @@ abstract class AbstractBot { if (!this.status) { return; } - if (tries > 2){ - this.cancelOrder(order.id); + if (tries > 1){ + this.cancelOrder(order); return } @@ -1340,7 +1343,7 @@ abstract class AbstractBot { console.log("CANCEL REPLACE: New clientOrderid: ", clientOrderId," PRICE:", price.toNumber(), " QTY: ", quantity.toNumber()); - //const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); + const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); //console.log("CANCEL REPLACE: GOT GASEST"); @@ -1351,7 +1354,7 @@ abstract class AbstractBot { order.side === 0 ? "BUY" : "SELL" } ::: ${quantity.toString()} ${this.base} @ ${price.toString()} ${this.quote}` ); - const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1500000)); + const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); const tx = await this.tradePair.cancelReplaceOrder(order.id, clientOrderId, priceToSend, quantityToSend, options); const orderLog = await tx.wait(); @@ -1431,7 +1434,7 @@ abstract class AbstractBot { } async processOpenOrders() { - this.logger.info(`${this.instanceName} Recovering open orders:`); + //this.logger.info(`${this.instanceName} Recovering open orders:`); const orders = await this.getOpenOrders(); if (orders){ for (const order of orders) { @@ -1459,7 +1462,7 @@ abstract class AbstractBot { } await this.checkOrdersInChain(); - this.logger.info(`${this.instanceName} open orders recovered:`); + //this.logger.info(`${this.instanceName} open orders recovered:`); return true; } @@ -1468,12 +1471,9 @@ abstract class AbstractBot { async checkOrdersInChain() { const promises: any = []; const orders: any = []; - const time = Date.now() for (const order of this.orders.values()) { - if ((time - order.timestamp)/1000 > this.interval/2 || !order.timestamp){ // If the order hasn't been updated within the interval time, check the chain to make sure we're not missing any information about it. - orders.push(order); - promises.push(this.tradePair.getOrder(order.id)); - } + orders.push(order); + promises.push(this.tradePair.getOrder(order.id)); } try { const results = await Promise.all(promises); @@ -1511,8 +1511,7 @@ abstract class AbstractBot { "0", "0", "0", - orderinMemory.level, - orderinMemory.timestamp + orderinMemory.level ); //tx, blocknbr , gasUsed, gasPrice, cumulativeGasUsed) ; const ordstatus = orderInChain.status; @@ -1931,11 +1930,11 @@ abstract class AbstractBot { async cleanUpAndExit() { if (!this.cleanupCalled) { - const timeout = 10; //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds + const timeout = 15; //Min 6 seconds because this.stop calls cancelall and waits for 5 seconds this.logger.warn(`${this.instanceName} === Process Exit Called === `); this.cleanupCalled = true; this.logger.warn(`${this.instanceName} === STOPPING === `); - await this.stop(); + this.stop(); setTimeout(() => { this.logger.warn(`${this.instanceName} === SHUTTING DOWN === `); diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index cd92189..25b4d5f 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -77,7 +77,7 @@ class MarketMakerBot extends AbstractBot { levels.push([0,i]); levels.push([1,i]); } - + await this.getBestOrders(); await this.placeInitialOrders(levels); // ------------ Begin Order Updater ------------ // @@ -103,7 +103,7 @@ class MarketMakerBot extends AbstractBot { } try { - if (this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance))){ + if (this.status && this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance))){ this.counter ++; this.timer = this.interval; console.log("000000000000000 COUNTER:",this.counter); @@ -112,18 +112,19 @@ class MarketMakerBot extends AbstractBot { if (this.tradePairIdentifier == "AVAX/USDt"){ await utils.sleep(500); } + await this.getBestOrders(); await this.correctNonce(this.contracts["SubNetProvider"]); let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); - const myBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; - const myBestBid = this.currentBestBid ? this.currentBestBid : undefined; + const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; + const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; let bids: any[] = []; let asks: any[] = []; let duplicates: any[] = []; this.orders.forEach((e,i)=>{ - if (e.side === 0 && e.level != undefined && e.level != -1){ + if (e.side === 0 && e.level > 0){ let skip = false; for (let i = 0;i 0) { let skip = false; for (let i = 0;i myBestAsk){ - console.log("BEST ASK: ",myBestAsk, "STARTING BID PRICE: ", startingBidPrice) - startingBidPrice = myBestAsk - (myBestAsk * this.orderLevelSpread); + if (currentBestAsk && startingBidPrice > currentBestAsk){ + console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) + startingBidPrice = currentBestAsk - (currentBestAsk * this.orderLevelSpread); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); - } else if (myBestBid && startingAskPrice < myBestBid){ - console.log("BEST BID: ",myBestBid, "STARTING ASK PRICE: ", startingAskPrice) - startingAskPrice = myBestBid + (myBestBid * this.orderLevelSpread); + } else if (currentBestBid && startingAskPrice < currentBestBid){ + console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) + startingAskPrice = currentBestBid + (currentBestBid * this.orderLevelSpread); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); @@ -189,7 +190,7 @@ class MarketMakerBot extends AbstractBot { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ if (this.status){ - await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice(),this.getBestOrders()]); + await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice()]); this.timer = 2000; this.updateOrders(); } @@ -202,8 +203,10 @@ class MarketMakerBot extends AbstractBot { async placeInitialOrders(levels: number[][]){ console.log("PLACING INITAL ORDERS: ",levels); - const initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); - const initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); + let initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); + let initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); + initialBidPrice = this.currentBestAsk && this.currentBestAsk < initialBidPrice ? this.currentBestAsk * (1-this.bidSpread) : initialBidPrice; + initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid * (1+this.askSpread) : initialAskPrice; let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // let bidsEnroute = 0; From 1ff6cf93c4dbe310eb13092e01ae7b1a05ae83a8 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 14:53:03 +0700 Subject: [PATCH 036/173] commented out some logger.errors that were shutting the bot down. --- services/bots/AbstractBot.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 456d99f..9e28864 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -422,7 +422,13 @@ abstract class AbstractBot { return new BigNumber(this.minTradeAmnt * (1 + Math.random() * 0.2)).div(price); } - async addLimitOrderList(newOrders: NewOrder[]) { + async addLimitOrderList(newOrders: NewOrder[], tries: number = 0) { + + if(tries > 2){ + this.cleanUpAndExit(); + return + } + const clientOrderIds = []; const prices = []; const quantities = []; @@ -543,7 +549,9 @@ abstract class AbstractBot { if (reason) { this.logger.warn(`${this.instanceName} addLimitOrderList error: Revert Reason ${reason}`); } else { - this.logger.error(`${this.instanceName} addLimitOrderList error:`, error); + //this.logger.error(`${this.instanceName} addLimitOrderList error:`, error); + console.log("FAILED TO ADD ORDER LIST. TRYING AGAIN...") + this.addLimitOrderList(newOrders,tries + 1); } } } @@ -1409,12 +1417,6 @@ abstract class AbstractBot { ); this.cancelReplaceOrder(order,price,quantity, tries +1); } else { - this.logger.error( - `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( - this.baseDisplayDecimals - )} @ ${price.toFixed(this.quoteDisplayDecimals)}`, - error - ); this.cancelReplaceOrder(order,price,quantity, tries +1); } } @@ -1541,7 +1543,8 @@ abstract class AbstractBot { return true; } } catch (error: any) { - this.logger.error(`${this.instanceName} Error during checkOrderInChain ${orderinMemory.clientOrderId}`, error); + //this.logger.error(`${this.instanceName} Error during checkOrderInChain ${orderinMemory.clientOrderId}`, error); + console.log("error during checkorderinchain", orderinMemory.clientOrderId, error) return false; } } From af760d43435cade4f9a0668d2e0941d2cfbcbcf6 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 14:56:49 +0700 Subject: [PATCH 037/173] If not enough funds to replace, cancel order so that it doesn't sit there forever --- services/bots/MarketMakerBot.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 25b4d5f..41e8d7f 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -270,6 +270,7 @@ class MarketMakerBot extends AbstractBot { this.cancelReplaceOrder(order,bidPrice,bidQty); } else { console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioAvail, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); + this.cancelOrder(order); } } else { console.log("MAKE FRESH ORDER:", order.id,order.status); @@ -299,6 +300,7 @@ class MarketMakerBot extends AbstractBot { this.cancelReplaceOrder(order,askPrice,askQty); } else { console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioAvail, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); + this.cancelOrder(order); } } else { console.log("MAKE FRESH ORDER"); From 80ea3c579bc48bf8154ccc881a6956dd6f4f12b6 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 16:33:29 +0700 Subject: [PATCH 038/173] comment out logger.error --- services/bots/AbstractBot.ts | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 9e28864..059d5e9 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -602,15 +602,15 @@ abstract class AbstractBot { const funds = this.fundsAvailable(side, quantity, marketPrice); if (side === 0) { if (!funds) { - this.logger.error(`${this.instanceName} Not enough funds to add BUY order`); - utils.printBalances(this.account, this.quote, this.contracts[this.quote]); + //this.logger.error(`${this.instanceName} Not enough funds to add BUY order`); + //utils.printBalances(this.account, this.quote, this.contracts[this.quote]); return; } this.checkWashTrade(side, price); } else { if (!funds) { - this.logger.error(`${this.instanceName} Not enough funds to add SELL order`); - utils.printBalances(this.account, this.base, this.contracts[this.base]); + //this.logger.error(`${this.instanceName} Not enough funds to add SELL order`); + //utils.printBalances(this.account, this.base, this.contracts[this.base]); return; } this.checkWashTrade(side, price); @@ -733,12 +733,12 @@ abstract class AbstractBot { } Revert Reason ${reason}` ); } else { - this.logger.error( - `${this.instanceName} addOrder error: ${side === 0 ? "BUY" : "SELL"} ${quantity ? quantity.toString() : "undefined"} @ ${ - price ? price.toString() : "undefined" - }`, - error - ); + // this.logger.error( + // `${this.instanceName} addOrder error: ${side === 0 ? "BUY" : "SELL"} ${quantity ? quantity.toString() : "undefined"} @ ${ + // price ? price.toString() : "undefined" + // }`, + // error + // ); } } } @@ -862,7 +862,7 @@ abstract class AbstractBot { const expectedNonce = await provider.provider.getTransactionCount(this.account); provider.nonce = expectedNonce; } catch (error) { - this.logger.error(`${this.instanceName} 'Error during nonce correction`, error); + //this.logger.error(`${this.instanceName} 'Error during nonce correction`, error); } } @@ -958,7 +958,7 @@ abstract class AbstractBot { //utils.printBalances(this.account, this.quote, this.contracts[this.quote]); } } catch (error) { - this.logger.error(`${this.instanceName} Error during getBalance`, error); + //this.logger.error(`${this.instanceName} Error during getBalance`, error); } } @@ -1066,7 +1066,7 @@ abstract class AbstractBot { } } } catch (error) { - this.logger.error(`${this.instanceName} Error during processOrders`, error); + // this.logger.error(`${this.instanceName} Error during processOrders`, error); } } @@ -1227,7 +1227,7 @@ abstract class AbstractBot { } } } catch (error) { - this.logger.error(`${this.instanceName} Error during CancelAll`, error); + //this.logger.error(`${this.instanceName} Error during CancelAll`, error); await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrderList(); } @@ -1239,7 +1239,7 @@ abstract class AbstractBot { await this.cancelOrder(order); } } catch (error) { - this.logger.error(`${this.instanceName} Error during cancelAllIndividually`, error); + //this.logger.error(`${this.instanceName} Error during cancelAllIndividually`, error); } } @@ -1312,12 +1312,12 @@ abstract class AbstractBot { this.removeOrderFromMap(order); } } else { - this.logger.error( - `${this.instanceName} Order Cancel error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( - this.baseDisplayDecimals - )} @ ${order.price.toFixed(this.quoteDisplayDecimals)}`, - error - ); + // this.logger.error( + // `${this.instanceName} Order Cancel error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( + // this.baseDisplayDecimals + // )} @ ${order.price.toFixed(this.quoteDisplayDecimals)}`, + // error + // ); } } return false; @@ -1431,7 +1431,7 @@ abstract class AbstractBot { .data; return orders.rows; } catch (error: any) { - this.logger.error(`${this.instanceName} ${error}`); + // this.logger.error(`${this.instanceName} ${error}`); } } From aafbd38a53328904be214d331ba25b58bb9dc28b Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 17:23:10 +0700 Subject: [PATCH 039/173] added promise error handling to getbestorders() --- services/bots/AbstractBot.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 059d5e9..5e6cf4e 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1410,12 +1410,16 @@ abstract class AbstractBot { } else { const reason = await this.getRevertReason(error); if (reason) { - this.logger.warn( - `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( - this.baseDisplayDecimals - )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` - ); - this.cancelReplaceOrder(order,price,quantity, tries +1); + if (reason == "T-OAEX-01"){ + this.removeOrderFromMap(order); + } else { + this.logger.warn( + `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( + this.baseDisplayDecimals + )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` + ); + this.cancelReplaceOrder(order,price,quantity, tries +1); + } } else { this.cancelReplaceOrder(order,price,quantity, tries +1); } @@ -1921,10 +1925,14 @@ abstract class AbstractBot { } async getBestOrders(){ + try { const currentBestBid = await this.orderBooks.getTopOfTheBook(this.orderBookID); const currentBestAsk = await this.orderBooks.getTopOfTheBook(this.orderBookID1); this.currentBestBid = currentBestBid.price.toNumber()/1000000; this.currentBestAsk = currentBestAsk.price.toNumber()/1000000; + } catch (error) { + console.log("error getting best orders:"); + } console.log(this.currentBestAsk); console.log(this.currentBestBid); From 24d715d74d65c54eed3ba2ae5b1c89b76731b121 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 17:33:56 +0700 Subject: [PATCH 040/173] remove unhandledRejection logic to end process --- services/bots/botLauncher.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/services/bots/botLauncher.ts b/services/bots/botLauncher.ts index 3fb5b03..88e34e8 100644 --- a/services/bots/botLauncher.ts +++ b/services/bots/botLauncher.ts @@ -37,5 +37,4 @@ process.on("uncaughtException", (error) => { process.on("unhandledRejection", (error, promise) => { console.log(`BotManager We forgot to handle a promise rejection here:`, promise); console.log(`BotManager The error was:`, error); - bot.cleanUpAndExit(); }); From 41541155e3202945ddf6064f55ce73c79f4b5a43 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 17:45:21 +0700 Subject: [PATCH 041/173] add timeout to retry cancelorderlist so it doesn't spam --- services/bots/AbstractBot.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 5e6cf4e..c4b8a7f 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1229,7 +1229,9 @@ abstract class AbstractBot { } catch (error) { //this.logger.error(`${this.instanceName} Error during CancelAll`, error); await this.correctNonce(this.contracts["SubNetProvider"]); - this.cancelOrderList(); + setTimeout(()=>{ + this.cancelOrderList(); + },2000); } } From 2f6589b6492a56d04c323e93419f8f16bc656434 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 18:24:23 +0700 Subject: [PATCH 042/173] move order sorting logic to order sorter. remove type 7 --- services/bots/MarketMakerBot.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 41e8d7f..fc56fd7 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -124,7 +124,7 @@ class MarketMakerBot extends AbstractBot { let duplicates: any[] = []; this.orders.forEach((e,i)=>{ - if (e.side === 0 && e.level > 0){ + if (e.side === 0 && e.level > 0 && (e.status == 0 || e.status == 2)){ let skip = false; for (let i = 0;i 0) { + } else if (e.side === 1 && e.level > 0 && (e.status == 0 || e.status == 2)) { let skip = false; for (let i = 0;i this.minTradeAmnt){ @@ -291,7 +291,7 @@ class MarketMakerBot extends AbstractBot { order = asksSorted[j]; } } - if (order.id && (order.status == 0 || order.status == 2 || order.status == 7)){ + if (order.id){ let askPrice = new BigNumber(startingAskPrice * (1+this.getSpread(i))); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioAvail + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ From 5bf59e24ca1545f914dd04ca7ae35844debb4ce9 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 18:33:27 +0700 Subject: [PATCH 043/173] add extra tries to cancel order and cancelReplace --- services/bots/AbstractBot.ts | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index c4b8a7f..951880e 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1245,7 +1245,10 @@ abstract class AbstractBot { } } - async cancelOrder(order: any) { + async cancelOrder(order: any, tries:number = 0) { + if (tries > 2){ + console.log("unable to cancel order:",order); + } try { // const gasest = await this.getCancelOrderGasEstimate(order); @@ -1302,6 +1305,9 @@ abstract class AbstractBot { )} @ ${order.price.toFixed(this.quoteDisplayDecimals)} Invalid Nonce` ); await this.correctNonce(this.contracts["SubNetProvider"]); + setTimeout(()=>{ + this.cancelOrder(order, tries+1); + }, 2000) } else { const reason = await this.getRevertReason(error); if (reason) { @@ -1312,14 +1318,15 @@ abstract class AbstractBot { ); if (reason === "T-OAEX-01") { this.removeOrderFromMap(order); + } else { + setTimeout(()=>{ + this.cancelOrder(order, tries+1); + }, 2000) } } else { - // this.logger.error( - // `${this.instanceName} Order Cancel error ${order.side === 0 ? "BUY" : "SELL"} ::: ${order.quantity.toFixed( - // this.baseDisplayDecimals - // )} @ ${order.price.toFixed(this.quoteDisplayDecimals)}`, - // error - // ); + setTimeout(()=>{ + this.cancelOrder(order, tries+1); + }, 2000) } } return false; @@ -1330,7 +1337,7 @@ abstract class AbstractBot { if (!this.status) { return; } - if (tries > 1){ + if (tries > 2){ this.cancelOrder(order); return } @@ -1408,7 +1415,9 @@ abstract class AbstractBot { )} @ ${price.toFixed(this.quoteDisplayDecimals)} Invalid Nonce` ); await this.correctNonce(this.contracts["SubNetProvider"]); - this.cancelReplaceOrder(order,price,quantity, tries +1); + setTimeout(()=>{ + this.cancelReplaceOrder(order,price,quantity, tries +1); + },2000) } else { const reason = await this.getRevertReason(error); if (reason) { @@ -1420,10 +1429,14 @@ abstract class AbstractBot { this.baseDisplayDecimals )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` ); - this.cancelReplaceOrder(order,price,quantity, tries +1); + setTimeout(()=>{ + this.cancelReplaceOrder(order,price,quantity, tries +1); + },2000) } } else { - this.cancelReplaceOrder(order,price,quantity, tries +1); + setTimeout(()=>{ + this.cancelReplaceOrder(order,price,quantity, tries +1); + },2000) } } return false; From 0242cfed2b87019b256736d9557c63ca2db4fc49 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 18 Jul 2023 18:46:52 +0700 Subject: [PATCH 044/173] add tries to addorder if issue with clientorderid --- services/bots/AbstractBot.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 951880e..e2a9dcd 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -565,9 +565,9 @@ abstract class AbstractBot { } } - async addOrder(side: number, qty: BigNumber | undefined, px: BigNumber | undefined, ordtype = 1, ordType2 = 3, level: number) { + async addOrder(side: number, qty: BigNumber | undefined, px: BigNumber | undefined, ordtype = 1, ordType2 = 3, level: number, tries: number = 0) { // LIMIT ORDER & GTC) - if (!this.status) { + if (!this.status || tries>2) { return; } @@ -732,6 +732,11 @@ abstract class AbstractBot { price ? price.toString() : "undefined" } Revert Reason ${reason}` ); + if (reason == "T-CLOI-01"){ + setTimeout(()=>{ + this.addOrder(side, qty, px, ordtype, ordType2, level, tries + 1); + }, 2000) + } } else { // this.logger.error( // `${this.instanceName} addOrder error: ${side === 0 ? "BUY" : "SELL"} ${quantity ? quantity.toString() : "undefined"} @ ${ From a4e34c46e17028f8abed2da180543b8efdf8c647 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 18 Jul 2023 19:14:58 +0700 Subject: [PATCH 045/173] fixed orderqty comparisons --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index fc56fd7..0a825a9 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -316,14 +316,14 @@ class MarketMakerBot extends AbstractBot { // console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds/price.toNumber() * .975){ return this.getLevelQty(level); - } else if (availableFunds/price.toNumber() *.975 > this.minTradeAmnt * 1.025){ + } else if (availableFunds *.975 > this.minTradeAmnt * 1.025){ return availableFunds/price.toNumber() *.975; } else { return 0;} } else if (side === 1) { // console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .975){ return this.getLevelQty(level); - } else if (availableFunds * .975 > this.minTradeAmnt * 1.025){ + } else if (availableFunds * price.toNumber() * .975 > this.minTradeAmnt * 1.025){ return availableFunds * .975; } else {return 0;} } else { From 934bac6eaa1d63849ee2a40d82e8ea0ee0cbbf55 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 18 Jul 2023 21:33:23 +0700 Subject: [PATCH 046/173] don't pass empty orderids to checkOrderOnChain --- services/bots/AbstractBot.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index e2a9dcd..d2c0696 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1504,7 +1504,11 @@ abstract class AbstractBot { try { const results = await Promise.all(promises); for (let i = 0; i < results.length; i++) { - this.checkOrderInChain(orders[i], results[i]); + if (!results[i]){ + this.removeOrderFromMap(orders[i]) + } else { + this.checkOrderInChain(orders[i], results[i]); + } // this.logger.debug( // `${this.instanceName} checkOrdersInChain: ${orders[i].side === 0 ? "BUY" : "SELL"} ${orders[i].quantity.toString()} ${ // this.base From 0cdad1276a5ef6ad8d2227938e9f7cc34cee87cb Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 18 Jul 2023 23:20:07 +0700 Subject: [PATCH 047/173] fix getqty available funds input --- services/bots/AbstractBot.ts | 23 ++++++++++++----------- services/bots/MarketMakerBot.ts | 26 ++++++++++++-------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index d2c0696..e460d51 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -503,9 +503,11 @@ abstract class AbstractBot { if (_log.event === "OrderStatusChanged") { if (_log.args.traderaddress === this.account && _log.args.pair === this.tradePairByte32) { let level = 0; + let quantity = new BigNumber(0); for (let i = 0; i < newOrders.length; i++){ if (newOrders[i].clientOrderId == _log.args.clientOrderId){ level = newOrders[i].level; + quantity = newOrders[i].quantity; } } await this.processOrders( @@ -516,7 +518,7 @@ abstract class AbstractBot { _log.args.clientOrderId, _log.args.price, _log.args.totalamount, - _log.args.quantity, + quantity, _log.args.side, _log.args.type1, _log.args.type2, @@ -693,7 +695,7 @@ abstract class AbstractBot { _log.args.clientOrderId, _log.args.price, _log.args.totalamount, - _log.args.quantity, + quantityToSend, _log.args.side, _log.args.type1, _log.args.type2, @@ -947,7 +949,6 @@ abstract class AbstractBot { bal = await portfolio.getBalance(this.account, this.contracts[this.base].inByte32); //baseBal this.contracts[this.base].portfolioTot = utils.formatUnits(bal.total, tokenDetails.evmdecimals); this.contracts[this.base].portfolioAvail = utils.formatUnits(bal.available, tokenDetails.evmdecimals); - //utils.printBalances(this.account, this.base, this.contracts[this.base]); } @@ -1393,7 +1394,7 @@ abstract class AbstractBot { _log.args.clientOrderId, _log.args.price, _log.args.totalamount, - _log.args.quantity, + quantityToSend, _log.args.side, _log.args.type1, _log.args.type2, @@ -1498,17 +1499,17 @@ abstract class AbstractBot { const promises: any = []; const orders: any = []; for (const order of this.orders.values()) { - orders.push(order); - promises.push(this.tradePair.getOrder(order.id)); + if (order.id){ + orders.push(order); + promises.push(this.tradePair.getOrder(order.id)); + } else { + this.removeOrderFromMap(order); + } } try { const results = await Promise.all(promises); for (let i = 0; i < results.length; i++) { - if (!results[i]){ - this.removeOrderFromMap(orders[i]) - } else { - this.checkOrderInChain(orders[i], results[i]); - } + this.checkOrderInChain(orders[i], results[i]); // this.logger.debug( // `${this.instanceName} checkOrdersInChain: ${orders[i].side === 0 ? "BUY" : "SELL"} ${orders[i].quantity.toString()} ${ // this.base diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 0a825a9..a0cee18 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -214,7 +214,7 @@ class MarketMakerBot extends AbstractBot { for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ let bidPrice = new BigNumber(initialBidPrice * (1-this.getSpread(levels[x][1]-1))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],this.contracts[this.quote].portfolioAvail - (bidsEnroute * bidPrice.toNumber()))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],parseFloat(this.contracts[this.quote].portfolioAvail) - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Avail: ",this.contracts[this.quote].portfolioAvail); bidsEnroute += bidQty.toNumber(); @@ -225,7 +225,7 @@ class MarketMakerBot extends AbstractBot { } else { //--------------- SET ASKS --------------- // let askPrice = new BigNumber(initialAskPrice * (1+this.getSpread(levels[x][1]-1))); - let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],this.contracts[this.base].portfolioAvail - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],parseFloat(this.contracts[this.base].portfolioAvail) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",this.contracts[this.base].portfolioAvail); asksEnRoute += askQty.toNumber(); @@ -255,7 +255,7 @@ class MarketMakerBot extends AbstractBot { let bidsEnRoute = 0; let skip = false; for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; + let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ order = bidsSorted[j]; @@ -263,17 +263,16 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let bidPrice = new BigNumber(startingBidPrice * (1-this.getSpread(i))); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,this.contracts[this.quote].portfolioAvail + (bidPrice.toNumber() * (order.totalamount.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - bidsEnRoute += (bidQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); + bidsEnRoute += (bidQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); this.cancelReplaceOrder(order,bidPrice,bidQty); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), this.contracts[this.quote].portfolioAvail, order.totalamount.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), parseFloat(this.contracts[this.quote].portfolioAvail), order.quantity.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); this.cancelOrder(order); } } else { - console.log("MAKE FRESH ORDER:", order.id,order.status); this.placeInitialOrders([[0,i+1]]); } } @@ -285,7 +284,7 @@ class MarketMakerBot extends AbstractBot { let skip = false; for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, totalamount:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; + let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ order = asksSorted[j]; @@ -293,17 +292,16 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let askPrice = new BigNumber(startingAskPrice * (1+this.getSpread(i))); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,this.contracts[this.base].portfolioAvail + (order.totalamount.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - asksEnRoute += (askQty.toNumber() - (order.totalamount.toNumber() - order.quantityfilled.toNumber())); + asksEnRoute += (askQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); console.log("REPLACE ORDER:",askPrice,askQty, i+1); this.cancelReplaceOrder(order,askPrice,askQty); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), this.contracts[this.base].portfolioAvail, order.totalamount.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); + console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), parseFloat(this.contracts[this.base].portfolioAvail), order.quantity.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); this.cancelOrder(order); } } else { - console.log("MAKE FRESH ORDER"); this.placeInitialOrders([[1,i+1]]); } } @@ -313,14 +311,14 @@ class MarketMakerBot extends AbstractBot { // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ - // console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds/price.toNumber() * .975){ return this.getLevelQty(level); } else if (availableFunds *.975 > this.minTradeAmnt * 1.025){ return availableFunds/price.toNumber() *.975; } else { return 0;} } else if (side === 1) { - // console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .975){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() * .975 > this.minTradeAmnt * 1.025){ From 15e3ee49de8122127aac3b2554d9bc762bf389f8 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 18 Jul 2023 23:40:15 +0700 Subject: [PATCH 048/173] cancel retry includes list --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index e460d51..3a94ad0 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1236,7 +1236,7 @@ abstract class AbstractBot { //this.logger.error(`${this.instanceName} Error during CancelAll`, error); await this.correctNonce(this.contracts["SubNetProvider"]); setTimeout(()=>{ - this.cancelOrderList(); + this.cancelOrderList(orderIds); },2000); } } From 807d419782fdd20dd74f457ad35d3c537adf5228 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Wed, 19 Jul 2023 00:09:21 +0700 Subject: [PATCH 049/173] add delays and get new nonces for retries --- services/bots/AbstractBot.ts | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 3a94ad0..d66e993 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -725,7 +725,11 @@ abstract class AbstractBot { } Invalid Nonce ` ); - await this.correctNonce(this.contracts["SubNetProvider"]); + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); + this.addOrder(side, qty, px, ordtype, ordType2, level, tries + 1); + + }, 2000) } else { const reason = await this.getRevertReason(error); if (reason) { @@ -1234,8 +1238,8 @@ abstract class AbstractBot { } } catch (error) { //this.logger.error(`${this.instanceName} Error during CancelAll`, error); - await this.correctNonce(this.contracts["SubNetProvider"]); - setTimeout(()=>{ + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrderList(orderIds); },2000); } @@ -1310,8 +1314,8 @@ abstract class AbstractBot { this.baseDisplayDecimals )} @ ${order.price.toFixed(this.quoteDisplayDecimals)} Invalid Nonce` ); - await this.correctNonce(this.contracts["SubNetProvider"]); - setTimeout(()=>{ + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrder(order, tries+1); }, 2000) } else { @@ -1325,12 +1329,14 @@ abstract class AbstractBot { if (reason === "T-OAEX-01") { this.removeOrderFromMap(order); } else { - setTimeout(()=>{ + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrder(order, tries+1); }, 2000) } } else { - setTimeout(()=>{ + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrder(order, tries+1); }, 2000) } @@ -1420,8 +1426,8 @@ abstract class AbstractBot { this.baseDisplayDecimals )} @ ${price.toFixed(this.quoteDisplayDecimals)} Invalid Nonce` ); - await this.correctNonce(this.contracts["SubNetProvider"]); - setTimeout(()=>{ + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelReplaceOrder(order,price,quantity, tries +1); },2000) } else { @@ -1435,12 +1441,14 @@ abstract class AbstractBot { this.baseDisplayDecimals )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` ); - setTimeout(()=>{ + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelReplaceOrder(order,price,quantity, tries +1); },2000) } } else { - setTimeout(()=>{ + setTimeout(async()=>{ + await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelReplaceOrder(order,price,quantity, tries +1); },2000) } From c8e7d041a6a05ac67c761d0e667b8768bdd51a1c Mon Sep 17 00:00:00 2001 From: beastlorion Date: Wed, 19 Jul 2023 16:16:28 +0700 Subject: [PATCH 050/173] moved refresh logic to beginning of order updater instead of periodically and removed some correcNonce calls from retries --- services/bots/AbstractBot.ts | 4 ---- services/bots/MarketMakerBot.ts | 31 ++++++++++++++++--------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index d66e993..5072966 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1330,13 +1330,11 @@ abstract class AbstractBot { this.removeOrderFromMap(order); } else { setTimeout(async()=>{ - await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrder(order, tries+1); }, 2000) } } else { setTimeout(async()=>{ - await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrder(order, tries+1); }, 2000) } @@ -1442,13 +1440,11 @@ abstract class AbstractBot { )} @ ${price.toFixed(this.quoteDisplayDecimals)} Revert Reason ${reason}` ); setTimeout(async()=>{ - await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelReplaceOrder(order,price,quantity, tries +1); },2000) } } else { setTimeout(async()=>{ - await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelReplaceOrder(order,price,quantity, tries +1); },2000) } diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index a0cee18..7122ff3 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -112,8 +112,8 @@ class MarketMakerBot extends AbstractBot { if (this.tradePairIdentifier == "AVAX/USDt"){ await utils.sleep(500); } - await this.getBestOrders(); - await this.correctNonce(this.contracts["SubNetProvider"]); + + await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; @@ -165,22 +165,23 @@ class MarketMakerBot extends AbstractBot { let bidsSorted = sortOrders(bids, "price", "descending"); let asksSorted = sortOrders(asks, "price", "ascending"); - // If there will be overlapping orders, wait for the orders of the side in which the price moved to be replaced first, then follow with the others. - if (currentBestAsk && startingBidPrice > currentBestAsk){ - console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) - startingBidPrice = currentBestAsk - (currentBestAsk * this.orderLevelSpread); + // If there will be overlapping orders, wait for the orders of the side in which the price moved to be replaced first, then follow with the others. + if (currentBestAsk && startingBidPrice > currentBestAsk){ + console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) + startingBidPrice = currentBestAsk - (currentBestAsk * this.orderLevelSpread); - await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); - } else if (currentBestBid && startingAskPrice < currentBestBid){ - console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) - startingAskPrice = currentBestBid + (currentBestBid * this.orderLevelSpread); + } else if (currentBestBid && startingAskPrice < currentBestBid){ + console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) + startingAskPrice = currentBestBid + (currentBestBid * this.orderLevelSpread); - await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); - } else { - await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); - } + } else { + await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + } + this.lastMarketPrice = this.marketPrice; } } catch (error) { @@ -190,7 +191,7 @@ class MarketMakerBot extends AbstractBot { //Update orders again after interval this.orderUpdater = setTimeout(async ()=>{ if (this.status){ - await Promise.all([this.getBalances(),this.processOpenOrders(),this.getNewMarketPrice()]); + await Promise.all([this.getNewMarketPrice()]); this.timer = 2000; this.updateOrders(); } From c9e84fa76884f6a88873312dcf99beb5e40fe5ff Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 01:58:43 +0700 Subject: [PATCH 051/173] add try/catch for gasest functions --- services/bots/AbstractBot.ts | 56 ++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 5072966..8d8e77b 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -620,7 +620,7 @@ abstract class AbstractBot { this.orderCount++; - //const gasest = await this.getAddOrderGasEstimate(clientOrderId, price, quantity, side, ordtype, ordType2); + const gasest = await this.getAddOrderGasEstimate(clientOrderId, price, quantity, side, ordtype, ordType2); // const tcost = await this.getTCost(gasest); // this.logger.debug (`${this.instanceName} New order gasEstimate: ${gasest} , tcost ${tcost.toString()} `); // this.logger.debug( @@ -631,7 +631,7 @@ abstract class AbstractBot { // this.logger.info (`${utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals)}`); // this.logger.info (`${utils.parseUnits(quantity.toFixed(this.baseDisplayDecimals), this.contracts[this.base].tokenDetails.evmdecimals)}`); - const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); + const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); const priceToSend = utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals); const quantityToSend = utils.parseUnits( @@ -818,16 +818,20 @@ abstract class AbstractBot { ordtype: number, ordType2: number ) { - return this.tradePair.estimateGas.addOrder( - this.account, - clientOrderId, - this.tradePairByte32, - utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals), - utils.parseUnits(quantity.toFixed(this.baseDisplayDecimals), this.contracts[this.base].tokenDetails.evmdecimals), - side, - ordtype, - ordType2 - ); + try { + return this.tradePair.estimateGas.addOrder( + this.account, + clientOrderId, + this.tradePairByte32, + utils.parseUnits(price.toFixed(this.quoteDisplayDecimals), this.contracts[this.quote].tokenDetails.evmdecimals), + utils.parseUnits(quantity.toFixed(this.baseDisplayDecimals), this.contracts[this.base].tokenDetails.evmdecimals), + side, + ordtype, + ordType2 + ); + } catch { + BigNumberEthers.from(1000000) + } } async getAddOrderListGasEstimate( @@ -837,19 +841,35 @@ abstract class AbstractBot { sides: number[], type2s: number[] ) { - return this.tradePair.estimateGas.addLimitOrderList(this.tradePairByte32, clientOrderIds, prices, quantities, sides, type2s); + try { + return this.tradePair.estimateGas.addLimitOrderList(this.tradePairByte32, clientOrderIds, prices, quantities, sides, type2s); + } catch { + return BigNumberEthers.from(1000000 * clientOrderIds.length); + } } async getCancelReplaceOrderGasEstimate(orderId: string, clientOrderId: string, price: BigNumberEthers, quantity: BigNumberEthers) { - return this.tradePair.estimateGas.cancelReplaceOrder(orderId, clientOrderId, price, quantity); + try { + return this.tradePair.estimateGas.cancelReplaceOrder(orderId, clientOrderId, price, quantity); + } catch { + return BigNumberEthers.from(1200000); + } } async getCancelOrderGasEstimate(order: any) { - return this.tradePair.estimateGas.cancelOrder(order.id); + try { + return this.tradePair.estimateGas.cancelOrder(order.id); + } catch { + return BigNumberEthers.from(1200000); + } } async getCancelAllOrdersGasEstimate(orderIds: string[]) { - return this.tradePair.estimateGas.cancelOrderList(orderIds); + try { + return this.tradePair.estimateGas.cancelOrderList(orderIds); + } catch { + return BigNumberEthers.from(1000000 * orderIds.length); + } } async getGasPriceInGwei(provider: any = this.contracts["SubNetProvider"]) { @@ -1260,7 +1280,7 @@ abstract class AbstractBot { console.log("unable to cancel order:",order); } try { - // const gasest = await this.getCancelOrderGasEstimate(order); + const gasest = await this.getCancelOrderGasEstimate(order); // this.logger.debug(`${this.instanceName} Cancel order gasEstimate: ${gasest} `); // ${tcost} this.orderCount++; @@ -1269,7 +1289,7 @@ abstract class AbstractBot { order.side === 0 ? "BUY" : "SELL" } ::: ${order.quantity.toString()} ${this.base} @ ${order.price.toString()} ${this.quote}` ); - const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1000000)); + const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); const tx = await this.tradePair.cancelOrder(order.id, options); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); //const orderLog = await this.race({ promise: tx.wait(), count: this.orderCount} ); From 4d9ed2a1887720941669877a8861a37f9403a081 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 12:08:59 +0700 Subject: [PATCH 052/173] add try/catch to get gas price function --- services/bots/AbstractBot.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 8d8e77b..063e979 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -789,10 +789,10 @@ abstract class AbstractBot { return reason; } - async getOptions(provider: any = this.contracts["SubNetProvider"], gasEstimate: BigNumberEthers = BigNumberEthers.from(700000)) { + async getOptions(provider: any = this.contracts["SubNetProvider"], gasEstimate: BigNumberEthers = BigNumberEthers.from(1000000)) { const gasPx = await this.getGasPrice(provider); - const maxFeePerGas = Math.ceil(gasPx.mul(115).div(100).toNumber()); - const gasLimit = Math.min(gasEstimate.mul(115).div(100).toNumber(), 30000000); // Block Gas Limit 30M + const maxFeePerGas = Math.ceil(gasPx.mul(120).div(100).toNumber()); + const gasLimit = Math.min(gasEstimate.mul(120).div(100).toNumber(), 30000000); // Block Gas Limit 30M const optionsWithNonce = { gasLimit, maxFeePerGas, maxPriorityFeePerGas: 1, nonce: 0 }; optionsWithNonce.nonce = provider.nonce++; @@ -882,7 +882,11 @@ abstract class AbstractBot { if (getConfig("NODE_ENV_SETTINGS") === "localdb-hh" || getConfig("NODE_ENV_SETTINGS") === "dev1-hh") { gasPx = BigNumberEthers.from(25000000000); } else { - gasPx = await provider.provider.getGasPrice(); + try { + gasPx = await provider.provider.getGasPrice(); + } catch { + gasPx = BigNumberEthers.from(25000000000); + } } return gasPx; } From 11b5c808cedd4de3a4f9b54e7768e5c5e2f760e0 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 12:22:25 +0700 Subject: [PATCH 053/173] slight adjustments to getQty --- services/bots/MarketMakerBot.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 7122ff3..84e9677 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -315,15 +315,15 @@ class MarketMakerBot extends AbstractBot { console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds/price.toNumber() * .975){ return this.getLevelQty(level); - } else if (availableFunds *.975 > this.minTradeAmnt * 1.025){ - return availableFunds/price.toNumber() *.975; + } else if (availableFunds > this.minTradeAmnt * 2){ + return availableFunds/price.toNumber() *.995; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds * .975){ + if (this.getLevelQty(level) < availableFunds * .995){ return this.getLevelQty(level); - } else if (availableFunds * price.toNumber() * .975 > this.minTradeAmnt * 1.025){ - return availableFunds * .975; + } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ + return availableFunds * .995; } else {return 0;} } else { return 0; // function declaration requires I return a number From ce971ed87ca2463704dc06a64a2f34b7ab54311e Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 13:39:12 +0700 Subject: [PATCH 054/173] fixed gasprice typo and adjust getqty to avoid out of funds errors --- services/bots/AbstractBot.ts | 19 ++++++++----------- services/bots/MarketMakerBot.ts | 16 ++++++++-------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 063e979..abf5486 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -69,6 +69,7 @@ abstract class AbstractBot { protected orderBookID1: any; protected currentBestBid: any; protected currentBestAsk: any; + protected counter: any; constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { this.logger = getLogger("Bot"); @@ -82,6 +83,7 @@ abstract class AbstractBot { this.orders = new Map(); this.orderbook = new OrderBook(); this.ratelimit_token = ratelimit_token; + this.counter = 0; (axios.defaults.headers! as unknown as Record).common["Origin"] = getConfig("ORIGIN_LINK"); (axios.defaults.headers! as unknown as Record).common["User-Agent"] = @@ -438,7 +440,8 @@ abstract class AbstractBot { const blocknumber = (await this.contracts["SubNetProvider"].provider.getBlockNumber()) || 0; for (let i = 0; i < newOrders.length; i++){ - const clientOrderId = await this.getClientOrderId(blocknumber, i); + this.counter ++ + const clientOrderId = await this.getClientOrderId(blocknumber, this.counter); newOrders[i].clientOrderId = clientOrderId; const priceToSend = utils.parseUnits( newOrders[i].price.toFixed(this.quoteDisplayDecimals), @@ -574,11 +577,8 @@ abstract class AbstractBot { } //get unique counter to generate clientOrderId - let counter = level; - if (level == 1){ - counter = counter + 100; - } - const clientOrderId = await this.getClientOrderId(0,counter); + this.counter ++ + const clientOrderId = await this.getClientOrderId(0,this.counter); let price = px; let quantity = qty; @@ -1385,11 +1385,8 @@ abstract class AbstractBot { this.contracts[this.base].tokenDetails.evmdecimals ); //get unique counter to generate clientOrderId - let counter = order.level; - if (order.side == 1){ - counter = counter + 100; - } - const clientOrderId = await this.getClientOrderId(0,counter); + this.counter ++ + const clientOrderId = await this.getClientOrderId(0,this.counter); // Not using the gasEstimate because it fails with P-AFNE1 when funds are tight but the actual C/R doesn't console.log("CANCEL REPLACE: New clientOrderid: ", clientOrderId," PRICE:", price.toNumber(), " QTY: ", quantity.toNumber()); diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 84e9677..266fb33 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -214,7 +214,7 @@ class MarketMakerBot extends AbstractBot { let asksEnRoute = 0; for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ - let bidPrice = new BigNumber(initialBidPrice * (1-this.getSpread(levels[x][1]-1))); + let bidPrice = new BigNumber((initialBidPrice * (1-this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],parseFloat(this.contracts[this.quote].portfolioAvail) - (bidsEnroute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Avail: ",this.contracts[this.quote].portfolioAvail); @@ -225,7 +225,7 @@ class MarketMakerBot extends AbstractBot { } } else { //--------------- SET ASKS --------------- // - let askPrice = new BigNumber(initialAskPrice * (1+this.getSpread(levels[x][1]-1))); + let askPrice = new BigNumber((initialAskPrice * (1+this.getSpread(levels[x][1]-1))).toFixed(this.baseDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],parseFloat(this.contracts[this.base].portfolioAvail) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",this.contracts[this.base].portfolioAvail); @@ -263,7 +263,7 @@ class MarketMakerBot extends AbstractBot { } } if (order.id){ - let bidPrice = new BigNumber(startingBidPrice * (1-this.getSpread(i))); + let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ bidsEnRoute += (bidQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); @@ -292,7 +292,7 @@ class MarketMakerBot extends AbstractBot { } } if (order.id){ - let askPrice = new BigNumber(startingAskPrice * (1+this.getSpread(i))); + let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ asksEnRoute += (askQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); @@ -313,17 +313,17 @@ class MarketMakerBot extends AbstractBot { getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds/price.toNumber() * .975){ + if (this.getLevelQty(level) < availableFunds/price.toNumber() * 0.99){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ - return availableFunds/price.toNumber() *.995; + return (availableFunds/price.toNumber()) *.95; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds * .995){ + if (this.getLevelQty(level) < availableFunds * .99){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ - return availableFunds * .995; + return availableFunds * .95; } else {return 0;} } else { return 0; // function declaration requires I return a number From 6ef0e737524ced5e49d906ce1647d0cfe3058c3a Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 14:51:27 +0700 Subject: [PATCH 055/173] fix getQty prices and processOpenOrders before closing orders when stopping --- services/bots/AbstractBot.ts | 3 ++- services/bots/MarketMakerBot.ts | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index abf5486..ee167ab 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -357,7 +357,8 @@ abstract class AbstractBot { if (this.orderUpdater !== undefined) { clearTimeout(this.orderUpdater); } - setTimeout(()=> { + setTimeout(async ()=> { + await this.processOpenOrders(); this.cancelOrderList([], 100) .then(() => { this.logger.warn(`${this.instanceName} Waiting 5 seconds before removing order listeners"...`); diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 266fb33..15401eb 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -266,7 +266,9 @@ class MarketMakerBot extends AbstractBot { let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - bidsEnRoute += (bidQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); + if (bidsEnRoute > 0){ + bidsEnRoute += (bidQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); + } console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); this.cancelReplaceOrder(order,bidPrice,bidQty); } else { @@ -274,7 +276,9 @@ class MarketMakerBot extends AbstractBot { this.cancelOrder(order); } } else { - this.placeInitialOrders([[0,i+1]]); + setTimeout(()=>{ + this.placeInitialOrders([[0,i+1]]); + },4000) } } } @@ -295,7 +299,9 @@ class MarketMakerBot extends AbstractBot { let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - asksEnRoute += (askQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); + if (asksEnRoute > 0){ + asksEnRoute += (askQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); + } console.log("REPLACE ORDER:",askPrice,askQty, i+1); this.cancelReplaceOrder(order,askPrice,askQty); } else { @@ -303,7 +309,9 @@ class MarketMakerBot extends AbstractBot { this.cancelOrder(order); } } else { - this.placeInitialOrders([[1,i+1]]); + setTimeout(()=>{ + this.placeInitialOrders([[1,i+1]]); + },4000) } } } @@ -316,14 +324,14 @@ class MarketMakerBot extends AbstractBot { if (this.getLevelQty(level) < availableFunds/price.toNumber() * 0.99){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ - return (availableFunds/price.toNumber()) *.95; + return (availableFunds/price.toNumber()) *.99; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .99){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ - return availableFunds * .95; + return availableFunds * .99; } else {return 0;} } else { return 0; // function declaration requires I return a number From 2658c0929559e8c6e79aa0def0994943106fc745 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 15:59:18 +0700 Subject: [PATCH 056/173] fix bug in placeinitalorders in bidsEnRoute --- services/bots/MarketMakerBot.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 15401eb..f9c179e 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -215,10 +215,10 @@ class MarketMakerBot extends AbstractBot { for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ let bidPrice = new BigNumber((initialBidPrice * (1-this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); - let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],parseFloat(this.contracts[this.quote].portfolioAvail) - (bidsEnroute * bidPrice.toNumber()))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],parseFloat(this.contracts[this.quote].portfolioAvail) - bidsEnroute)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Avail: ",this.contracts[this.quote].portfolioAvail); - bidsEnroute += bidQty.toNumber(); + bidsEnroute += bidQty.toNumber() * bidPrice.toNumber(); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } else { console.log("NOT ENOUGH FUNDS TO PLACE INITIAL BID: ", levels[x][1]) @@ -264,10 +264,10 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) - (bidsEnRoute * bidPrice.toNumber()))); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) - bidsEnRoute)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ if (bidsEnRoute > 0){ - bidsEnRoute += (bidQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); + bidsEnRoute += bidQty.toNumber() * bidPrice.toNumber() - ((order.quantity.toNumber() - order.quantityfilled.toNumber()) * bidPrice.toNumber()); } console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); this.cancelReplaceOrder(order,bidPrice,bidQty); From 9d0f9b229d836fa5209d67c86958614317455b4f Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 16:07:36 +0700 Subject: [PATCH 057/173] add .01% quantity buffer when recycling cancelreplace quanities --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index f9c179e..9f3bf56 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -264,7 +264,7 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) - bidsEnRoute)); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) * .99 - bidsEnRoute)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ if (bidsEnRoute > 0){ bidsEnRoute += bidQty.toNumber() * bidPrice.toNumber() - ((order.quantity.toNumber() - order.quantityfilled.toNumber()) * bidPrice.toNumber()); @@ -297,7 +297,7 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) * .99 - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ if (asksEnRoute > 0){ asksEnRoute += (askQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); From b6533ece874d2c6c7938e1f62c9c8601e045805e Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 16:13:15 +0700 Subject: [PATCH 058/173] lower buffer --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9f3bf56..fa94807 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -264,7 +264,7 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) * .99 - bidsEnRoute)); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) * .999 - bidsEnRoute)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ if (bidsEnRoute > 0){ bidsEnRoute += bidQty.toNumber() * bidPrice.toNumber() - ((order.quantity.toNumber() - order.quantityfilled.toNumber()) * bidPrice.toNumber()); @@ -297,7 +297,7 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) * .99 - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) * .999 - asksEnRoute)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ if (asksEnRoute > 0){ asksEnRoute += (askQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); From 6d3f811375b094fb5c26fb26b31295ce0b19f652 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 23:21:07 +0700 Subject: [PATCH 059/173] rehaul the available funds variable to efficiently place funds in orders --- services/bots/AbstractBot.ts | 6 ++-- services/bots/MarketMakerBot.ts | 62 ++++++++++++++++----------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index ee167ab..7f4f53f 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -427,7 +427,7 @@ abstract class AbstractBot { async addLimitOrderList(newOrders: NewOrder[], tries: number = 0) { - if(tries > 2){ + if(tries > 1){ this.cleanUpAndExit(); return } @@ -573,7 +573,7 @@ abstract class AbstractBot { async addOrder(side: number, qty: BigNumber | undefined, px: BigNumber | undefined, ordtype = 1, ordType2 = 3, level: number, tries: number = 0) { // LIMIT ORDER & GTC) - if (!this.status || tries>2) { + if (!this.status || tries>1) { return; } @@ -1372,7 +1372,7 @@ abstract class AbstractBot { if (!this.status) { return; } - if (tries > 2){ + if (tries > 1){ this.cancelOrder(order); return } diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index fa94807..3bab069 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -10,7 +10,7 @@ class MarketMakerBot extends AbstractBot { protected baseUsd = 0; protected quoteUsd = 0; protected capitalASideUSD = 300; - protected counter = 0; + protected orderUpdaterCounter = 0; protected lastMarketPrice = new BigNumber(0); protected bidSpread: any; protected askSpread: any; @@ -104,9 +104,9 @@ class MarketMakerBot extends AbstractBot { try { if (this.status && this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance))){ - this.counter ++; + this.orderUpdaterCounter ++; this.timer = this.interval; - console.log("000000000000000 COUNTER:",this.counter); + console.log("000000000000000 COUNTER:",this.orderUpdaterCounter); // having issues with nonces when avax/usdc and avax/usdt send orders at the same time. This gives priority to avaxusdc if (this.tradePairIdentifier == "AVAX/USDt"){ @@ -201,7 +201,7 @@ class MarketMakerBot extends AbstractBot { // Takes in an array of arrays. The first number of each subarray is the side, the second is the level. // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList - async placeInitialOrders(levels: number[][]){ + async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ console.log("PLACING INITAL ORDERS: ",levels); let initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); @@ -210,15 +210,13 @@ class MarketMakerBot extends AbstractBot { initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid * (1+this.askSpread) : initialAskPrice; let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // - let bidsEnroute = 0; - let asksEnRoute = 0; for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ let bidPrice = new BigNumber((initialBidPrice * (1-this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); - let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],parseFloat(this.contracts[this.quote].portfolioAvail) - bidsEnroute)); + let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],availableQuote)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Avail: ",this.contracts[this.quote].portfolioAvail); - bidsEnroute += bidQty.toNumber() * bidPrice.toNumber(); + availableQuote -= bidQty.toNumber() * bidPrice.toNumber(); + console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Avail: ",availableQuote); newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); } else { console.log("NOT ENOUGH FUNDS TO PLACE INITIAL BID: ", levels[x][1]) @@ -226,10 +224,10 @@ class MarketMakerBot extends AbstractBot { } else { //--------------- SET ASKS --------------- // let askPrice = new BigNumber((initialAskPrice * (1+this.getSpread(levels[x][1]-1))).toFixed(this.baseDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],parseFloat(this.contracts[this.base].portfolioAvail) - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],availableBase)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",this.contracts[this.base].portfolioAvail); - asksEnRoute += askQty.toNumber(); + availableBase -= askQty.toNumber(); + console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",availableBase); newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); } else { console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK: ", levels[x][1]) @@ -253,31 +251,35 @@ class MarketMakerBot extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); - let bidsEnRoute = 0; - let skip = false; + let availableQuote = parseFloat(this.contracts[this.quote].portfolioTot); for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; + if (availableQuote < this.minTradeAmnt * 2){ + break; + } + let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ order = bidsSorted[j]; } } + if (order.id){ let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,parseFloat(this.contracts[this.quote].portfolioAvail) + (bidPrice.toNumber() * (order.quantity.toNumber() - order.quantityfilled.toNumber())) * .999 - bidsEnRoute)); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableQuote)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - if (bidsEnRoute > 0){ - bidsEnRoute += bidQty.toNumber() * bidPrice.toNumber() - ((order.quantity.toNumber() - order.quantityfilled.toNumber()) * bidPrice.toNumber()); - } + availableQuote -= bidQty.toNumber() * bidPrice.toNumber(); console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); this.cancelReplaceOrder(order,bidPrice,bidQty); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), parseFloat(this.contracts[this.quote].portfolioAvail), order.quantity.toNumber(), order.quantityfilled.toNumber(), bidsEnRoute); + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), availableQuote); this.cancelOrder(order); } } else { + //set aside funds to create new orders + let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); + availableQuote -= this.getLevelQty(i+1) * bidPrice.toNumber() * 1.01; setTimeout(()=>{ - this.placeInitialOrders([[0,i+1]]); + this.placeInitialOrders([[0,i+1]],availableQuote,); },4000) } } @@ -285,8 +287,7 @@ class MarketMakerBot extends AbstractBot { async replaceAsks (asksSorted: any, startingAskPrice: number){ console.log("REPLACE ASKS: ",asksSorted.length); - let asksEnRoute = 0; - let skip = false; + let availableBase = parseFloat(this.contracts[this.base].portfolioTot); for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; @@ -297,20 +298,19 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,parseFloat(this.contracts[this.base].portfolioAvail) + (order.quantity.toNumber() - order.quantityfilled.toNumber()) * .999 - asksEnRoute)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableBase)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - if (asksEnRoute > 0){ - asksEnRoute += (askQty.toNumber() - (order.quantity.toNumber() - order.quantityfilled.toNumber())); - } + availableBase -= askQty.toNumber(); console.log("REPLACE ORDER:",askPrice,askQty, i+1); this.cancelReplaceOrder(order,askPrice,askQty); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), parseFloat(this.contracts[this.base].portfolioAvail), order.quantity.toNumber(), order.quantityfilled.toNumber(), asksEnRoute); + console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), availableBase); this.cancelOrder(order); } } else { + availableBase -= this.getLevelQty(i+1) * 1.01; setTimeout(()=>{ - this.placeInitialOrders([[1,i+1]]); + this.placeInitialOrders([[1,i+1]],undefined,availableBase); },4000) } } @@ -324,14 +324,14 @@ class MarketMakerBot extends AbstractBot { if (this.getLevelQty(level) < availableFunds/price.toNumber() * 0.99){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ - return (availableFunds/price.toNumber()) *.99; + return availableFunds/price.toNumber() * .975; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .99){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ - return availableFunds * .99; + return availableFunds * .975; } else {return 0;} } else { return 0; // function declaration requires I return a number From e9637ff8e90e6bbf9fa7787f231d475938082bb4 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 21 Jul 2023 23:28:50 +0700 Subject: [PATCH 060/173] lower getqty partial buffer to .99 from .975 --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 3bab069..f5fb1ef 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -324,14 +324,14 @@ class MarketMakerBot extends AbstractBot { if (this.getLevelQty(level) < availableFunds/price.toNumber() * 0.99){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ - return availableFunds/price.toNumber() * .975; + return availableFunds/price.toNumber() * .99; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .99){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ - return availableFunds * .975; + return availableFunds * .99; } else {return 0;} } else { return 0; // function declaration requires I return a number From d1a9d99842c61dfe64fc323c8e8d1c7ffb3960d8 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 00:23:41 +0700 Subject: [PATCH 061/173] remove break from replace bids --- services/bots/MarketMakerBot.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index f5fb1ef..ad8a579 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -201,7 +201,7 @@ class MarketMakerBot extends AbstractBot { // Takes in an array of arrays. The first number of each subarray is the side, the second is the level. // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList - async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ + async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioTot, availableBase: number = this.contracts[this.base].portfolioTot){ console.log("PLACING INITAL ORDERS: ",levels); let initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); @@ -253,9 +253,6 @@ class MarketMakerBot extends AbstractBot { console.log("REPLACE BIDS: ",bidsSorted.length); let availableQuote = parseFloat(this.contracts[this.quote].portfolioTot); for (let i = 0; i < this.orderLevels; i ++){ - if (availableQuote < this.minTradeAmnt * 2){ - break; - } let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ From 779f1013589fe530a66935a613c67f63510ab3f6 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 01:30:44 +0700 Subject: [PATCH 062/173] fixed issue with available fudns for addorder during replace orders --- services/bots/MarketMakerBot.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index ad8a579..48f85b2 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -274,10 +274,9 @@ class MarketMakerBot extends AbstractBot { } else { //set aside funds to create new orders let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - availableQuote -= this.getLevelQty(i+1) * bidPrice.toNumber() * 1.01; - setTimeout(()=>{ - this.placeInitialOrders([[0,i+1]],availableQuote,); - },4000) + let amount = this.getLevelQty(i+1) * bidPrice.toNumber() * 1.01; + availableQuote -= amount + this.placeInitialOrders([[0,i+1]],amount,); } } } @@ -305,10 +304,9 @@ class MarketMakerBot extends AbstractBot { this.cancelOrder(order); } } else { - availableBase -= this.getLevelQty(i+1) * 1.01; - setTimeout(()=>{ - this.placeInitialOrders([[1,i+1]],undefined,availableBase); - },4000) + let amount = this.getLevelQty(i+1) * 1.01; + this.placeInitialOrders([[1,i+1]],undefined,amount); + availableBase -= amount; } } } From 1e9ffd2a67056967b6d7164a4503f87e339f42d8 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 01:42:48 +0700 Subject: [PATCH 063/173] fix issue with adding order inside replace orders --- services/bots/MarketMakerBot.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 48f85b2..ee368ec 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -275,8 +275,13 @@ class MarketMakerBot extends AbstractBot { //set aside funds to create new orders let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); let amount = this.getLevelQty(i+1) * bidPrice.toNumber() * 1.01; - availableQuote -= amount - this.placeInitialOrders([[0,i+1]],amount,); + if (amount < availableQuote){ + availableQuote -= amount + this.placeInitialOrders([[0,i+1]],amount,); + } else { + this.placeInitialOrders([[0,i+1]],availableQuote,); + availableQuote = 0; + } } } } @@ -305,8 +310,13 @@ class MarketMakerBot extends AbstractBot { } } else { let amount = this.getLevelQty(i+1) * 1.01; - this.placeInitialOrders([[1,i+1]],undefined,amount); - availableBase -= amount; + if (amount < availableBase){ + this.placeInitialOrders([[1,i+1]],undefined,amount); + availableBase -= amount; + } else { + this.placeInitialOrders([[1,i+1]],undefined,availableBase); + availableBase = 0; + } } } } From f3f3f81aa3a8f7ce4d29041fa947c25d46442469 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 11:02:31 +0700 Subject: [PATCH 064/173] use startingbid price to calculate quantity instead of actual bid price --- services/bots/MarketMakerBot.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index ee368ec..5bfe8a5 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -264,7 +264,7 @@ class MarketMakerBot extends AbstractBot { let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableQuote)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - availableQuote -= bidQty.toNumber() * bidPrice.toNumber(); + availableQuote -= bidQty.toNumber() * startingBidPrice; // Using startingBidPrice here so that slightly less base asset is used than is available. console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); this.cancelReplaceOrder(order,bidPrice,bidQty); } else { @@ -273,8 +273,7 @@ class MarketMakerBot extends AbstractBot { } } else { //set aside funds to create new orders - let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let amount = this.getLevelQty(i+1) * bidPrice.toNumber() * 1.01; + let amount = this.getLevelQty(i+1) * startingBidPrice; if (amount < availableQuote){ availableQuote -= amount this.placeInitialOrders([[0,i+1]],amount,); @@ -329,14 +328,14 @@ class MarketMakerBot extends AbstractBot { if (this.getLevelQty(level) < availableFunds/price.toNumber() * 0.99){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ - return availableFunds/price.toNumber() * .99; + return availableFunds/price.toNumber() * .9999; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .99){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ - return availableFunds * .99; + return availableFunds * .9999; } else {return 0;} } else { return 0; // function declaration requires I return a number From 12e2bffbd9530257b9bf5f28090c3eaa3624822f Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 13:00:54 +0700 Subject: [PATCH 065/173] fix some issues with available funds variables in replacebids --- services/bots/MarketMakerBot.ts | 67 +++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 5bfe8a5..376db8e 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -251,7 +251,8 @@ class MarketMakerBot extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); - let availableQuote = parseFloat(this.contracts[this.quote].portfolioTot); + let quoteTot = parseFloat(this.contracts[this.quote].portfolioTot); + let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; for (let j = 0; j < bidsSorted.length; j++){ @@ -262,24 +263,32 @@ class MarketMakerBot extends AbstractBot { if (order.id){ let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableQuote)); - if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - availableQuote -= bidQty.toNumber() * startingBidPrice; // Using startingBidPrice here so that slightly less base asset is used than is available. - console.log("REPLACE ORDER:",bidPrice,bidQty, i+1); - this.cancelReplaceOrder(order,bidPrice,bidQty); + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber(); + let availableFunds = quoteAvail + amountOnOrder; + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,quoteTot)); + let amountToPlace = bidQty; + if (availableFunds < amountToPlace.toNumber() * bidPrice.toNumber()){ + amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())); + } + if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + quoteTot -= bidQty.toNumber() * bidPrice.toNumber(); // How much we would ideally place. This will take some off of the later orders to refill this one on the next update + console.log("REPLACE ORDER:",amountToPlace.toNumber(),bidQty.toNumber(), i+1); + quoteAvail -= amountToPlace.toNumber() * bidPrice.toNumber() - amountOnOrder + this.cancelReplaceOrder(order,bidPrice,amountToPlace); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), availableQuote); + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), quoteTot, quoteAvail, availableFunds, amountOnOrder, amountToPlace.toNumber()); this.cancelOrder(order); } } else { //set aside funds to create new orders let amount = this.getLevelQty(i+1) * startingBidPrice; - if (amount < availableQuote){ - availableQuote -= amount + quoteTot -= amount; // How much we would ideally place. This will take some off of the later orders to refill this one on the next update + if (amount < quoteAvail){ + quoteAvail -= amount; this.placeInitialOrders([[0,i+1]],amount,); } else { - this.placeInitialOrders([[0,i+1]],availableQuote,); - availableQuote = 0; + this.placeInitialOrders([[0,i+1]],quoteAvail,); + quoteAvail = 0; } } } @@ -287,7 +296,8 @@ class MarketMakerBot extends AbstractBot { async replaceAsks (asksSorted: any, startingAskPrice: number){ console.log("REPLACE ASKS: ",asksSorted.length); - let availableBase = parseFloat(this.contracts[this.base].portfolioTot); + let baseTot = parseFloat(this.contracts[this.base].portfolioTot); + let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; @@ -297,24 +307,33 @@ class MarketMakerBot extends AbstractBot { } } if (order.id){ + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .999; + let availableFunds = baseAvail + amountOnOrder; + let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableBase)); - if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - availableBase -= askQty.toNumber(); - console.log("REPLACE ORDER:",askPrice,askQty, i+1); - this.cancelReplaceOrder(order,askPrice,askQty); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,baseTot)); + let amountToPlace = askQty; + if (availableFunds < askQty.toNumber()){ + amountToPlace = new BigNumber(availableFunds * .999); + } + + if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + baseTot -= askQty.toNumber(); // How much we would ideally place. This will take some off of the later orders to refill this one on the next update + console.log("REPLACE ORDER:",askPrice.toNumber(),amountToPlace.toNumber(), i+1); + this.cancelReplaceOrder(order,askPrice,amountToPlace); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", askQty.toNumber(), availableBase); + console.log("NOT ENOUGH FUNDS TO REPLACE", amountToPlace.toNumber(), baseTot, baseAvail); this.cancelOrder(order); } } else { let amount = this.getLevelQty(i+1) * 1.01; - if (amount < availableBase){ + baseTot -= amount; // How much we would ideally place. This will take some off of the later orders to refill this one on the next update + if (amount < baseAvail){ this.placeInitialOrders([[1,i+1]],undefined,amount); - availableBase -= amount; + baseAvail -= amount; } else { - this.placeInitialOrders([[1,i+1]],undefined,availableBase); - availableBase = 0; + this.placeInitialOrders([[1,i+1]],undefined,baseAvail); + baseAvail = 0; } } } @@ -328,14 +347,14 @@ class MarketMakerBot extends AbstractBot { if (this.getLevelQty(level) < availableFunds/price.toNumber() * 0.99){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ - return availableFunds/price.toNumber() * .9999; + return availableFunds/price.toNumber() * .999; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds * .99){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ - return availableFunds * .9999; + return availableFunds * .999; } else {return 0;} } else { return 0; // function declaration requires I return a number From 7d14ebbc44cdb152f3a98dd79160ac0d2c4080f4 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 13:44:37 +0700 Subject: [PATCH 066/173] add slight buffer to bidamount --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 376db8e..a1702c9 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -268,7 +268,7 @@ class MarketMakerBot extends AbstractBot { let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,quoteTot)); let amountToPlace = bidQty; if (availableFunds < amountToPlace.toNumber() * bidPrice.toNumber()){ - amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())); + amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); } if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ quoteTot -= bidQty.toNumber() * bidPrice.toNumber(); // How much we would ideally place. This will take some off of the later orders to refill this one on the next update From 8d30ba0622bb2db91051dff088dcacc3ed490b38 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 14:07:42 +0700 Subject: [PATCH 067/173] pass in available funds instead of portfoliotot for bidqty calc --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index a1702c9..26041fd 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -265,7 +265,7 @@ class MarketMakerBot extends AbstractBot { let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber(); let availableFunds = quoteAvail + amountOnOrder; - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,quoteTot)); + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); let amountToPlace = bidQty; if (availableFunds < amountToPlace.toNumber() * bidPrice.toNumber()){ amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); From 4d66491d6d991944ca5fdc53d62de4f23a6d4ba0 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 14:45:46 +0700 Subject: [PATCH 068/173] fix bug in getqty --- services/bots/MarketMakerBot.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 26041fd..4c56199 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -267,7 +267,7 @@ class MarketMakerBot extends AbstractBot { let availableFunds = quoteAvail + amountOnOrder; let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); let amountToPlace = bidQty; - if (availableFunds < amountToPlace.toNumber() * bidPrice.toNumber()){ + if (availableFunds/bidPrice.toNumber() < amountToPlace.toNumber()){ amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); } if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ @@ -344,14 +344,14 @@ class MarketMakerBot extends AbstractBot { getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds/price.toNumber() * 0.99){ + if (this.getLevelQty(level) < availableFunds/price.toNumber()){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ return availableFunds/price.toNumber() * .999; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) - if (this.getLevelQty(level) < availableFunds * .99){ + if (this.getLevelQty(level) < availableFunds){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ return availableFunds * .999; From 895f384e562ca89a2d92b92b19e916155ac6771b Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 22 Jul 2023 18:54:10 +0700 Subject: [PATCH 069/173] fix placeAsks availableFunds and portfolioavail. Removed portfoliotot --- services/bots/MarketMakerBot.ts | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 4c56199..9cf5dbc 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -201,7 +201,7 @@ class MarketMakerBot extends AbstractBot { // Takes in an array of arrays. The first number of each subarray is the side, the second is the level. // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList - async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioTot, availableBase: number = this.contracts[this.base].portfolioTot){ + async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ console.log("PLACING INITAL ORDERS: ",levels); let initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); @@ -251,7 +251,6 @@ class MarketMakerBot extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); - let quoteTot = parseFloat(this.contracts[this.quote].portfolioTot); let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; @@ -263,7 +262,7 @@ class MarketMakerBot extends AbstractBot { if (order.id){ let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber(); + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.999; let availableFunds = quoteAvail + amountOnOrder; let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); let amountToPlace = bidQty; @@ -271,18 +270,16 @@ class MarketMakerBot extends AbstractBot { amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); } if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - quoteTot -= bidQty.toNumber() * bidPrice.toNumber(); // How much we would ideally place. This will take some off of the later orders to refill this one on the next update console.log("REPLACE ORDER:",amountToPlace.toNumber(),bidQty.toNumber(), i+1); - quoteAvail -= amountToPlace.toNumber() * bidPrice.toNumber() - amountOnOrder + quoteAvail -= bidQty.toNumber() * bidPrice.toNumber() - amountOnOrder this.cancelReplaceOrder(order,bidPrice,amountToPlace); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), quoteTot, quoteAvail, availableFunds, amountOnOrder, amountToPlace.toNumber()); + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), quoteAvail, availableFunds, amountOnOrder, amountToPlace.toNumber()); this.cancelOrder(order); } } else { //set aside funds to create new orders let amount = this.getLevelQty(i+1) * startingBidPrice; - quoteTot -= amount; // How much we would ideally place. This will take some off of the later orders to refill this one on the next update if (amount < quoteAvail){ quoteAvail -= amount; this.placeInitialOrders([[0,i+1]],amount,); @@ -296,7 +293,6 @@ class MarketMakerBot extends AbstractBot { async replaceAsks (asksSorted: any, startingAskPrice: number){ console.log("REPLACE ASKS: ",asksSorted.length); - let baseTot = parseFloat(this.contracts[this.base].portfolioTot); let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); for (let i = 0; i < this.orderLevels; i ++){ @@ -311,23 +307,21 @@ class MarketMakerBot extends AbstractBot { let availableFunds = baseAvail + amountOnOrder; let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,baseTot)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); let amountToPlace = askQty; if (availableFunds < askQty.toNumber()){ amountToPlace = new BigNumber(availableFunds * .999); } - + baseAvail -= askQty.toNumber() - amountOnOrder; if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - baseTot -= askQty.toNumber(); // How much we would ideally place. This will take some off of the later orders to refill this one on the next update console.log("REPLACE ORDER:",askPrice.toNumber(),amountToPlace.toNumber(), i+1); this.cancelReplaceOrder(order,askPrice,amountToPlace); } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", amountToPlace.toNumber(), baseTot, baseAvail); + console.log("NOT ENOUGH FUNDS TO REPLACE", amountToPlace.toNumber(), availableFunds); this.cancelOrder(order); } } else { let amount = this.getLevelQty(i+1) * 1.01; - baseTot -= amount; // How much we would ideally place. This will take some off of the later orders to refill this one on the next update if (amount < baseAvail){ this.placeInitialOrders([[1,i+1]],undefined,amount); baseAvail -= amount; From 5b4cc06a28341fb857ad4b9d6bb80996722e2936 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 27 Jul 2023 12:24:48 +0700 Subject: [PATCH 070/173] give funds priority to further back orders instead of small close to market orders --- services/bots/MarketMakerBot.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9cf5dbc..baa8eab 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -210,7 +210,7 @@ class MarketMakerBot extends AbstractBot { initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid * (1+this.askSpread) : initialAskPrice; let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // - for (let x = 0; x < levels.length; x++){ + for (let x = levels.length-1; x >= 0; x--){ if (levels[x][0] == 0){ let bidPrice = new BigNumber((initialBidPrice * (1-this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],availableQuote)); @@ -230,14 +230,14 @@ class MarketMakerBot extends AbstractBot { console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",availableBase); newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); } else { - console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK: ", levels[x][1]) + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK LEVEL: ", levels[x][1]) } } } // // --------------- EXECUTE ORDERS --------------- // if (newOrderList.length == 0){ - console.log("ERROR - NewOrderList empty"); + console.log("NewOrderList empty"); } else if (newOrderList.length == 1){ if (this.status){ this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); @@ -252,7 +252,7 @@ class MarketMakerBot extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); - for (let i = 0; i < this.orderLevels; i ++){ + for (let i = this.orderLevels.length - 1; i >= 0; i --){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ @@ -295,7 +295,7 @@ class MarketMakerBot extends AbstractBot { console.log("REPLACE ASKS: ",asksSorted.length); let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); - for (let i = 0; i < this.orderLevels; i ++){ + for (let i = this.orderLevels.length -1; i >= 0; i --){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ From c0700c82441dee8717d9512fc42dd3f0813ddfde Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 27 Jul 2023 12:43:37 +0700 Subject: [PATCH 071/173] fix bug in replace loops --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index baa8eab..5d6e078 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -252,7 +252,7 @@ class MarketMakerBot extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); - for (let i = this.orderLevels.length - 1; i >= 0; i --){ + for (let i = this.orderLevels - 1; i >= 0; i --){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ @@ -295,7 +295,7 @@ class MarketMakerBot extends AbstractBot { console.log("REPLACE ASKS: ",asksSorted.length); let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); - for (let i = this.orderLevels.length -1; i >= 0; i --){ + for (let i = this.orderLevels -1; i >= 0; i --){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ From a0df3db4408ce9b0ededbcd9bfbb01e4c43c035e Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 27 Jul 2023 12:52:10 +0700 Subject: [PATCH 072/173] give fund priority back to closer orders --- services/bots/MarketMakerBot.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 5d6e078..9cf5dbc 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -210,7 +210,7 @@ class MarketMakerBot extends AbstractBot { initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid * (1+this.askSpread) : initialAskPrice; let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // - for (let x = levels.length-1; x >= 0; x--){ + for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ let bidPrice = new BigNumber((initialBidPrice * (1-this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],availableQuote)); @@ -230,14 +230,14 @@ class MarketMakerBot extends AbstractBot { console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",availableBase); newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); } else { - console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK LEVEL: ", levels[x][1]) + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK: ", levels[x][1]) } } } // // --------------- EXECUTE ORDERS --------------- // if (newOrderList.length == 0){ - console.log("NewOrderList empty"); + console.log("ERROR - NewOrderList empty"); } else if (newOrderList.length == 1){ if (this.status){ this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); @@ -252,7 +252,7 @@ class MarketMakerBot extends AbstractBot { async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length); let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); - for (let i = this.orderLevels - 1; i >= 0; i --){ + for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; for (let j = 0; j < bidsSorted.length; j++){ if (bidsSorted[j].level == i+1){ @@ -295,7 +295,7 @@ class MarketMakerBot extends AbstractBot { console.log("REPLACE ASKS: ",asksSorted.length); let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); - for (let i = this.orderLevels -1; i >= 0; i --){ + for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; for (let j = 0; j < asksSorted.length; j++){ if (asksSorted[j].level == i+1){ From 9ad522ad99c70b1d284057e59b62446971edae7f Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 28 Jul 2023 22:49:36 +0700 Subject: [PATCH 073/173] add support for sAVAX/AVAX. Calls benqi savax contract for sAVAX redemption rate --- artifacts/contracts/savaxABI.json | 1 + services/bots/AbstractBot.ts | 7 +++++++ services/bots/MarketMakerBot.ts | 21 ++++++++++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 artifacts/contracts/savaxABI.json diff --git a/artifacts/contracts/savaxABI.json b/artifacts/contracts/savaxABI.json new file mode 100644 index 0000000..cf15567 --- /dev/null +++ b/artifacts/contracts/savaxABI.json @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"AccrueRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldCooldownPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCooldownPeriod","type":"uint256"}],"name":"CooldownPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"MintingPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"MintingResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"unlockRequestedAt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"avaxAmount","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"RedeemOverdueShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRedeemPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRedeemPeriod","type":"uint256"}],"name":"RedeemPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"avaxAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"Submitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldTotalPooldAvaxCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalPooledAvaxCap","type":"uint256"}],"name":"TotalPooledAvaxCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"unlockRequestedAt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"UnlockCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"UnlockRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_ACCRUE_REWARDS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_DEPOSIT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_PAUSE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_PAUSE_MINTING","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_RESUME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_RESUME_MINTING","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_SET_TOTAL_POOLED_AVAX_CAP","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_WITHDRAW","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"accrueRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelPendingUnlockRequests","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelRedeemableUnlockRequests","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unlockIndex","type":"uint256"}],"name":"cancelUnlockRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldownPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"}],"name":"getPaginatedUnlockRequests","outputs":[{"components":[{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"shareAmount","type":"uint256"}],"internalType":"struct StakedAvaxStorage.UnlockRequest[]","name":"","type":"tuple[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"getPooledAvaxByShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"avaxAmount","type":"uint256"}],"name":"getSharesByPooledAvax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUnlockRequestCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"historicalExchangeRateTimestamps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"historicalExchangeRatesByTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cooldownPeriod","type":"uint256"},{"internalType":"uint256","name":"_redeemPeriod","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unlockIndex","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemOverdueShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unlockIndex","type":"uint256"}],"name":"redeemOverdueShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareAmount","type":"uint256"}],"name":"requestUnlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resumeMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCooldownPeriod","type":"uint256"}],"name":"setCooldownPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRedeemPeriod","type":"uint256"}],"name":"setRedeemPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newTotalPooledAvaxCap","type":"uint256"}],"name":"setTotalPooledAvaxCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"submit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalPooledAvax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPooledAvaxCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userSharesInCustody","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userUnlockRequests","outputs":[{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"shareAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 7f4f53f..763354b 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -14,6 +14,7 @@ import OrderBook from "./orderbook"; import NewOrder from "./classes"; import ERC20ABI from "../../artifacts/contracts/ERC20.json"; +import savaxABI from "../../artifacts/contracts/savaxABI.json"; import OrderBookRecordRaw from "../../models/orderBookRecordRaw"; import OrderBookRaw from "../../models/orderBookRaw"; const apiUrl = getConfig("API_URL") + "privapi/trading/"; @@ -67,6 +68,7 @@ abstract class AbstractBot { protected orderBooks: any; protected orderBookID: any; protected orderBookID1: any; + protected savaxContract: any; protected currentBestBid: any; protected currentBestAsk: any; protected counter: any; @@ -261,6 +263,11 @@ abstract class AbstractBot { this.orderBookID1 = await this.tradePair.getBookId(this.tradePairByte32,1); await this.getBestOrders(); + if (this.base == "sAVAX"){ + this.savaxContract = new ethers.Contract("0x2b2C81e08f1Af8835a78Bb2A90AE924ACE0eA4bE",savaxABI,this.contracts["MainnetWallet"]); + } + + this.minTradeAmnt = this.pairObject.mintrade_amnt; this.maxTradeAmnt = this.pairObject.maxtrade_amnt; this.quoteDisplayDecimals = this.pairObject.quotedisplaydecimals; diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9cf5dbc..badee74 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -20,8 +20,7 @@ class MarketMakerBot extends AbstractBot { protected refreshOrderTolerance: any; protected flatAmount: any; protected timer: any; - // protected bestAsk: any; - // protected bestBid: any; + protected lastBaseUsd: any; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -368,12 +367,24 @@ class MarketMakerBot extends AbstractBot { try { let response = await axios.get('http://localhost:3000/prices'); let prices = response.data; - + this.baseUsd = prices[this.base+'-USD']; this.quoteUsd = prices[this.quote+'-USD']; - this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); - console.log("new market Price:",this.marketPrice.toNumber()); + if (this.base == "sAVAX"){ + let totalPooledAvax = await this.savaxContract.totalPooledAvax(); + let totalSupply = await this.savaxContract.totalSupply(); + totalPooledAvax = new BigNumber(totalPooledAvax.toString()); + totalSupply = new BigNumber(totalSupply.toString()); + + this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9992; + } + if (this.baseUsd && this.quoteUsd){ + this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); + console.log("new market Price:",this.marketPrice.toNumber()); + } else { + throw 'trouble getting base or quote prices' + } } catch (error: any) { this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); } From 20ff4e45776429da2dabd5e0c552105a83a45198 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 3 Aug 2023 12:07:19 +0700 Subject: [PATCH 074/173] add TakerBot, fix code in BotFactory --- package.json | 5 +- services/bots/BotFactory.ts | 8 +- services/bots/TakerBot.ts | 205 ++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 services/bots/TakerBot.ts diff --git a/package.json b/package.json index a9205f7..a727562 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,9 @@ "private": true, "author": "Cengiz Dincoglu", "scripts": { - "marketMaker-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=fuji", - "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --NODE_ENV_SETTINGS=production" + "marketMaker-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMaker --NODE_ENV_SETTINGS=fuji", + "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMaker --NODE_ENV_SETTINGS=production", + "taker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=taker --NODE_ENV_SETTINGS=production" }, "dependencies": { "@ethersproject/experimental": "5.7.0", diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index 3652c26..d5eed42 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -1,8 +1,10 @@ import MarketMakerBot from "./MarketMakerBot"; -const Bot:any = MarketMakerBot; +import TakerBot from "./TakerBot"; +const Bot:any = {marketMaker: MarketMakerBot, taker:TakerBot}; module.exports = { createBot(type:any, attributes:any) { - return new Bot(attributes.botId,attributes.pairStr,attributes.privateKey); + const BotType = Bot[type]; + return new BotType(attributes.botId,attributes.pairStr,attributes.privateKey); } -}; +}; \ No newline at end of file diff --git a/services/bots/TakerBot.ts b/services/bots/TakerBot.ts new file mode 100644 index 0000000..e8c9dc9 --- /dev/null +++ b/services/bots/TakerBot.ts @@ -0,0 +1,205 @@ +import axios from "axios"; +import { getConfig } from "../../config"; +import utils from "../utils"; +import BigNumber from "bignumber.js"; +import AbstractBot from "./AbstractBot"; +import NewOrder from "./classes"; + +class MarketMakerBot extends AbstractBot { + protected marketPrice = new BigNumber(0); + protected baseUsd = 0; + protected quoteUsd = 0; + protected bidSpread: any; + protected askSpread: any; + protected flatAmount: any; + protected timer: any; + protected capitalASideUSD = 300; + + constructor(botId: number, pairStr: string, privateKey: string) { + super(botId, pairStr, privateKey); + // Will try to rebalance the amounts in the Portfolio Contract + this.portfolioRebalanceAtStart = false; + this.config = getConfig(this.tradePairIdentifier); + this.config = this.config.taker; + this.bidSpread = this.config.bidSpread/100; + this.askSpread = this.config.askSpread/100; + this.flatAmount = this.config.flatAmount; + } + + async saveBalancestoDb(balancesRefreshed: boolean): Promise { + this.logger.info(`${this.instanceName} Save Balances somewhere if needed`); + } + + async initialize(): Promise { + const initializing = await super.initialize(); + if (initializing) { + await this.getNewMarketPrice(); + // await this.getBestOrders(); + + this.interval = 5000; + + // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc + //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); + + return true; + } else { + return false; + } + } + + async startOrderUpdater() { + if (this.status) { + // Sleep 30 seconds initially if rebalancing portfolio + if (this.portfolioRebalanceAtStart){ + await utils.sleep(30000); + } + + this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); + + //Cancel any remaining orders + await this.cancelOrderList([], 100); + + if (this.baseUsd && this.quoteUsd){ + + await this.getBestOrders(); + + // ------------ Begin Order Updater ------------ // + + this.orderUpdater = setTimeout(()=>{ + this.updateOrders(); + }, this.interval/2); + } else { + console.log("MISSING PRICE DATA - baseUsd:",this.baseUsd, " quoteUsd: ",this.quoteUsd, "Wait 10 seconds then try again"); + await utils.sleep(10000); + await this.getNewMarketPrice(); + this.startOrderUpdater(); + } + } else { + this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); + } + } + + async updateOrders() { + if (this.orderUpdater != undefined) { + clearTimeout(this.orderUpdater); + } + if (this.orders.values.length > 0){ + await this.cancelOrderList([],100); + this.timer = 6000; + } + + try { + if (this.status && (this.marketPrice.toNumber() * (1 - this.bidSpread) > this.currentBestAsk || this.marketPrice.toNumber() * (1 + this.askSpread) > this.currentBestBid)){ + this.timer = this.interval; + + // having issues with nonces when avax/usdc and avax/usdt send orders at the same time in the same wallet. This gives priority to avaxusdc. + if (this.tradePairIdentifier == "AVAX/USDt"){ + await utils.sleep(500); + } + await Promise.all([this.getBalances(),this.correctNonce(this.contracts["SubNetProvider"])]); + + if (this.marketPrice.toNumber() * (1 - this.bidSpread) > this.currentBestAsk){ + const bidPrice = new BigNumber(this.marketPrice.toNumber() * (1 - this.bidSpread)); + let quantity = this.getQuantity(bidPrice, 0); + this.addOrder(0,quantity,bidPrice,1,2,0); // immediate or cancel order + } + if (this.marketPrice.toNumber() * (1 + this.askSpread) < this.currentBestBid){ + const askPrice = new BigNumber(this.marketPrice.toNumber() * (1 + this.askSpread)); + let quantity = this.getQuantity(askPrice, 1); + this.addOrder(1,quantity,askPrice,1,2,0); // immediate or cancel order + } + + + } + } catch (error) { + this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); + this.cleanUpAndExit(); + } finally { + //Update orders again after interval + this.orderUpdater = setTimeout(async ()=>{ + if (this.status){ + await Promise.all([this.getNewMarketPrice(),this.getBestOrders(),this.processOpenOrders()]); + this.timer = 2000; + this.updateOrders(); + } + }, this.timer); + } + } + + getQuantity(price: BigNumber, side: number): BigNumber { + if (side == 0){ + if (this.contracts[this.quote].portfolioAvail / price.toNumber() > this.flatAmount){ + return new BigNumber(this.flatAmount); + } else { + return new BigNumber(this.contracts[this.quote].portfolioAvail / price.toNumber()); + } + } else { + if (this.contracts[this.base].portfolioAvail > this.flatAmount){ + return new BigNumber(this.flatAmount); + } else { + return new BigNumber(this.contracts[this.base].portfolioAvail); + } + } + } + + // Update the marketPrice from an outside source + async getNewMarketPrice() { + try { + let response = await axios.get('http://localhost:3000/prices'); + let prices = response.data; + + this.baseUsd = prices[this.base+'-USD']; + this.quoteUsd = prices[this.quote+'-USD']; + + if (this.base == "sAVAX"){ + let totalPooledAvax = await this.savaxContract.totalPooledAvax(); + let totalSupply = await this.savaxContract.totalSupply(); + totalPooledAvax = new BigNumber(totalPooledAvax.toString()); + totalSupply = new BigNumber(totalSupply.toString()); + + this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9992; + } + if (this.baseUsd && this.quoteUsd){ + this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); + console.log("new market Price:",this.marketPrice.toNumber()); + } else { + throw 'trouble getting base or quote prices' + } + } catch (error: any) { + this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); + } + return this.marketPrice; + } + + getPrice(side: number): BigNumber { + return this.marketPrice; + } + + async getAlotPrice(): Promise { + let alotprice = 0.25; + try { + alotprice = 0.25; // FIXME Implement your own price source to get the ALOT price + } catch (error) { + this.logger.error(`${this.instanceName} Error during getAlotPrice`, error); + } + return alotprice; + } + getBaseCapital(): number { + if (this.baseUsd) { + return parseFloat((this.capitalASideUSD / this.baseUsd).toFixed(this.baseDisplayDecimals)); + } else { + return this.initialDepositBase; + } + } + + getQuoteCapital(): number { + if (this.quoteUsd) { + return parseFloat((this.capitalASideUSD / this.quoteUsd).toFixed(this.quoteDisplayDecimals)); + } else { + return this.initialDepositQuote; + } + } + +} + +export default MarketMakerBot; From c1dca21234ca84e89dec1a33512309d337298435 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 3 Aug 2023 12:19:33 +0700 Subject: [PATCH 075/173] fix bug with decimal rounding on asks --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index badee74..a84c46f 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -222,7 +222,7 @@ class MarketMakerBot extends AbstractBot { } } else { //--------------- SET ASKS --------------- // - let askPrice = new BigNumber((initialAskPrice * (1+this.getSpread(levels[x][1]-1))).toFixed(this.baseDisplayDecimals)); + let askPrice = new BigNumber((initialAskPrice * (1+this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],availableBase)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ availableBase -= askQty.toNumber(); @@ -305,7 +305,7 @@ class MarketMakerBot extends AbstractBot { let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .999; let availableFunds = baseAvail + amountOnOrder; - let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.baseDisplayDecimals)); + let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); let amountToPlace = askQty; if (availableFunds < askQty.toNumber()){ From 2de24191e267b68f6e52d0a51bac003648d85905 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 3 Aug 2023 13:50:48 +0700 Subject: [PATCH 076/173] add exception for savax/avax in getBestOrders() because for some reason it returns a much larger number than the other pairs --- services/bots/AbstractBot.ts | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 763354b..9304495 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -256,13 +256,6 @@ abstract class AbstractBot { this.tradePair = new ethers.Contract(deployment.address, deployment.abi.abi, this.contracts["SubnetWallet"]); this.contracts["TradePairs"].deployedContract = this.tradePair; - - deployment = this.contracts["OrderBooks"]; - this.orderBooks = new ethers.Contract(deployment.address, deployment.abi.abi, this.contracts["SubnetWallet"]); - this.orderBookID = await this.tradePair.getBookId(this.tradePairByte32,0); - this.orderBookID1 = await this.tradePair.getBookId(this.tradePairByte32,1); - await this.getBestOrders(); - if (this.base == "sAVAX"){ this.savaxContract = new ethers.Contract("0x2b2C81e08f1Af8835a78Bb2A90AE924ACE0eA4bE",savaxABI,this.contracts["MainnetWallet"]); } @@ -272,6 +265,12 @@ abstract class AbstractBot { this.maxTradeAmnt = this.pairObject.maxtrade_amnt; this.quoteDisplayDecimals = this.pairObject.quotedisplaydecimals; this.baseDisplayDecimals = this.pairObject.basedisplaydecimals; + + deployment = this.contracts["OrderBooks"]; + this.orderBooks = new ethers.Contract(deployment.address, deployment.abi.abi, this.contracts["SubnetWallet"]); + this.orderBookID = await this.tradePair.getBookId(this.tradePairByte32,0); + this.orderBookID1 = await this.tradePair.getBookId(this.tradePairByte32,1); + await this.getBestOrders(); let avaxLoaded; @@ -1984,12 +1983,20 @@ abstract class AbstractBot { async getBestOrders(){ try { - const currentBestBid = await this.orderBooks.getTopOfTheBook(this.orderBookID); - const currentBestAsk = await this.orderBooks.getTopOfTheBook(this.orderBookID1); - this.currentBestBid = currentBestBid.price.toNumber()/1000000; - this.currentBestAsk = currentBestAsk.price.toNumber()/1000000; + let currentBestBidResponse = await this.orderBooks.getTopOfTheBook(this.orderBookID); + let currentBestAskResponse = await this.orderBooks.getTopOfTheBook(this.orderBookID1); + let currentBestBid = new BigNumber(currentBestBidResponse.price.toString())//.dp(this.quoteDisplayDecimals); + let currentBestAsk = new BigNumber(currentBestAskResponse.price.toString())//.dp(this.quoteDisplayDecimals); + if (this.tradePairIdentifier=="sAVAX/AVAX"){ + this.currentBestBid = currentBestBid.div("1000000000000000000").toNumber() + this.currentBestAsk = currentBestAsk.div("1000000000000000000").toNumber() + } else { + this.currentBestBid = currentBestBid.div(1000000).toNumber() + this.currentBestAsk = currentBestAsk.div(1000000).toNumber() + } + } catch (error) { - console.log("error getting best orders:"); + console.log("error getting best orders:",error); } console.log(this.currentBestAsk); console.log(this.currentBestBid); From a06859bee842cb523991bbc9c3aa1e12b9a92e24 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 4 Aug 2023 00:18:26 +0700 Subject: [PATCH 077/173] fix bestorder price adjustments --- services/bots/MarketMakerBot.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index a84c46f..be11e23 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -164,16 +164,18 @@ class MarketMakerBot extends AbstractBot { let bidsSorted = sortOrders(bids, "price", "descending"); let asksSorted = sortOrders(asks, "price", "ascending"); - // If there will be overlapping orders, wait for the orders of the side in which the price moved to be replaced first, then follow with the others. + + if (currentBestAsk && startingBidPrice > currentBestAsk){ console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) - startingBidPrice = currentBestAsk - (currentBestAsk * this.orderLevelSpread); + + startingBidPrice = currentBestAsk - this.getIncrement(); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); } else if (currentBestBid && startingAskPrice < currentBestBid){ console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) - startingAskPrice = currentBestBid + (currentBestBid * this.orderLevelSpread); + startingAskPrice = currentBestBid + this.getIncrement(); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); @@ -205,8 +207,10 @@ class MarketMakerBot extends AbstractBot { let initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); let initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); - initialBidPrice = this.currentBestAsk && this.currentBestAsk < initialBidPrice ? this.currentBestAsk * (1-this.bidSpread) : initialBidPrice; - initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid * (1+this.askSpread) : initialAskPrice; + initialBidPrice = this.currentBestAsk && this.currentBestAsk < initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; + initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; + + console.log(initialAskPrice,initialBidPrice,this.currentBestAsk, this.currentBestBid, 'slkdfjsld'); let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // for (let x = 0; x < levels.length; x++){ @@ -421,10 +425,17 @@ class MarketMakerBot extends AbstractBot { } } - // async getBestOrders(){ - // this.bestBid = getBottomOfTheBook - // this.bestAsk = getTopOfTheBook - // } + getIncrement(): number { + let increment = '0.'; + for (let i = 0; i < this.quoteDisplayDecimals; i++){ + if (i < this.quoteDisplayDecimals - 1){ + increment += '0' + } else { + increment += '1' + } + } + return parseFloat(increment); + } } From 80f6d3fb6b042123832dfa189e2539be0b30b871 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 4 Aug 2023 00:18:48 +0700 Subject: [PATCH 078/173] remove comment --- services/bots/MarketMakerBot.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index be11e23..6c12bae 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -210,7 +210,6 @@ class MarketMakerBot extends AbstractBot { initialBidPrice = this.currentBestAsk && this.currentBestAsk < initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; - console.log(initialAskPrice,initialBidPrice,this.currentBestAsk, this.currentBestBid, 'slkdfjsld'); let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // for (let x = 0; x < levels.length; x++){ From 0165d30a172d2c48fb4b84f811d3f6c15f6977de Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 5 Aug 2023 14:15:41 +0700 Subject: [PATCH 079/173] add timestamp lastUpdated for marketMaker to replace orders --- services/bots/MarketMakerBot.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 6c12bae..777ee8a 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -21,6 +21,7 @@ class MarketMakerBot extends AbstractBot { protected flatAmount: any; protected timer: any; protected lastBaseUsd: any; + protected lastUpdate: any; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -102,8 +103,9 @@ class MarketMakerBot extends AbstractBot { } try { - if (this.status && this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance))){ + if (this.status && ((Date.now() - this.lastUpdate)/1000 > 900 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ this.orderUpdaterCounter ++; + this.lastUpdate = Date.now(); this.timer = this.interval; console.log("000000000000000 COUNTER:",this.orderUpdaterCounter); From 41fd81f0e620fda70fa708fe078cdac9db8a4b9d Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 5 Aug 2023 14:58:30 +0700 Subject: [PATCH 080/173] round to decimal before deciding whether to adjust bid/ask price due to bestOrders prices --- services/bots/MarketMakerBot.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 777ee8a..bcb65fa 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -207,10 +207,10 @@ class MarketMakerBot extends AbstractBot { async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ console.log("PLACING INITAL ORDERS: ",levels); - let initialBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); - let initialAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); - initialBidPrice = this.currentBestAsk && this.currentBestAsk < initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; - initialAskPrice = this.currentBestBid && this.currentBestBid > initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; + let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); + let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); + initialBidPrice = this.currentBestAsk && this.currentBestAsk <= initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; + initialAskPrice = this.currentBestBid && this.currentBestBid >= initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; let newOrderList : NewOrder[] = []; // --------------- SET BIDS --------------- // From b638717f93c8e9a3a027bfc52971c65a30fa776d Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 5 Aug 2023 15:03:28 +0700 Subject: [PATCH 081/173] adjust savax price buffer --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index bcb65fa..123557e 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -382,7 +382,7 @@ class MarketMakerBot extends AbstractBot { totalPooledAvax = new BigNumber(totalPooledAvax.toString()); totalSupply = new BigNumber(totalSupply.toString()); - this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9992; + this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9988; } if (this.baseUsd && this.quoteUsd){ this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); From eea6e5244b804dd1bded4d2a4c33d2bdbae3d8d2 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 5 Aug 2023 15:08:01 +0700 Subject: [PATCH 082/173] adjust savax price buffer to .9979 --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 123557e..a182ea0 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -382,7 +382,7 @@ class MarketMakerBot extends AbstractBot { totalPooledAvax = new BigNumber(totalPooledAvax.toString()); totalSupply = new BigNumber(totalSupply.toString()); - this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9988; + this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9979; } if (this.baseUsd && this.quoteUsd){ this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); From e6b59dc506741cf6525fcae4758b6f8938b1a881 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 5 Aug 2023 15:46:45 +0700 Subject: [PATCH 083/173] use rounded prices for comparing for replacing orders --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index a182ea0..3bcd709 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -115,8 +115,8 @@ class MarketMakerBot extends AbstractBot { } await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); - let startingBidPrice = this.marketPrice.toNumber() * (1-this.bidSpread); - let startingAskPrice = this.marketPrice.toNumber() * (1+this.askSpread); + let startingBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); + let startingAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; From 58dbee80e2b3633ede3ce412c12cb3eb075b3782 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Wed, 16 Aug 2023 10:10:51 +0700 Subject: [PATCH 084/173] decrease savax discount to .15% --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 3bcd709..ccb274a 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -382,7 +382,7 @@ class MarketMakerBot extends AbstractBot { totalPooledAvax = new BigNumber(totalPooledAvax.toString()); totalSupply = new BigNumber(totalSupply.toString()); - this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9979; + this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9985; } if (this.baseUsd && this.quoteUsd){ this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); From 5c5031ac67eaf39038d662ef0bb3ceea7b3cf98e Mon Sep 17 00:00:00 2001 From: beastlorion Date: Wed, 16 Aug 2023 16:12:54 +0700 Subject: [PATCH 085/173] switching savax to custom price feed --- services/bots/MarketMakerBot.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index ccb274a..9924481 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -373,16 +373,13 @@ class MarketMakerBot extends AbstractBot { let response = await axios.get('http://localhost:3000/prices'); let prices = response.data; - this.baseUsd = prices[this.base+'-USD']; - this.quoteUsd = prices[this.quote+'-USD']; if (this.base == "sAVAX"){ - let totalPooledAvax = await this.savaxContract.totalPooledAvax(); - let totalSupply = await this.savaxContract.totalSupply(); - totalPooledAvax = new BigNumber(totalPooledAvax.toString()); - totalSupply = new BigNumber(totalSupply.toString()); - - this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9985; + this.quoteUsd = prices[this.quote+'-USD']; + this.baseUsd = prices['sAVAX-AVAX'] * this.quoteUsd; + } else { + this.baseUsd = prices[this.base+'-USD']; + this.quoteUsd = prices[this.quote+'-USD']; } if (this.baseUsd && this.quoteUsd){ this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); From fa98e63b7162745229864e8cf1b85876f04ea77a Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 25 Aug 2023 11:50:30 +0700 Subject: [PATCH 086/173] add bot type using order lists instead of cancelreplace --- filePath | 1 + package.json | 1 + services/bots/AbstractBot.ts | 15 +- services/bots/BotFactory.ts | 3 +- services/bots/MarketMakerBotOrderLists.ts | 454 ++++++++++++++++++++++ 5 files changed, 468 insertions(+), 6 deletions(-) create mode 100644 filePath create mode 100644 services/bots/MarketMakerBotOrderLists.ts diff --git a/filePath b/filePath new file mode 100644 index 0000000..e21b88f --- /dev/null +++ b/filePath @@ -0,0 +1 @@ +{nonce:13421} \ No newline at end of file diff --git a/package.json b/package.json index a727562..9a9f97a 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "marketMaker-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMaker --NODE_ENV_SETTINGS=fuji", "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMaker --NODE_ENV_SETTINGS=production", + "marketMakerLists-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMakerLists --NODE_ENV_SETTINGS=production", "taker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=taker --NODE_ENV_SETTINGS=production" }, "dependencies": { diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 9304495..581667d 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -72,6 +72,7 @@ abstract class AbstractBot { protected currentBestBid: any; protected currentBestAsk: any; protected counter: any; + protected lastNonce: any; constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { this.logger = getLogger("Bot"); @@ -802,7 +803,7 @@ abstract class AbstractBot { const gasLimit = Math.min(gasEstimate.mul(120).div(100).toNumber(), 30000000); // Block Gas Limit 30M const optionsWithNonce = { gasLimit, maxFeePerGas, maxPriorityFeePerGas: 1, nonce: 0 }; - optionsWithNonce.nonce = provider.nonce++; + optionsWithNonce.nonce = this.lastNonce++; return optionsWithNonce; } @@ -858,7 +859,8 @@ abstract class AbstractBot { async getCancelReplaceOrderGasEstimate(orderId: string, clientOrderId: string, price: BigNumberEthers, quantity: BigNumberEthers) { try { return this.tradePair.estimateGas.cancelReplaceOrder(orderId, clientOrderId, price, quantity); - } catch { + } catch (err){ + console.log("getCancelReplaceOrderGasEstimate error:",err); return BigNumberEthers.from(1200000); } } @@ -891,7 +893,8 @@ abstract class AbstractBot { } else { try { gasPx = await provider.provider.getGasPrice(); - } catch { + } catch (err) { + console.log("getGasPrice error:", err) gasPx = BigNumberEthers.from(25000000000); } } @@ -903,6 +906,9 @@ abstract class AbstractBot { try { const expectedNonce = await provider.provider.getTransactionCount(this.account); provider.nonce = expectedNonce; + if (provider == this.contracts["SubNetProvider"]){ + this.lastNonce = provider.nonce; + } } catch (error) { //this.logger.error(`${this.instanceName} 'Error during nonce correction`, error); } @@ -1230,7 +1236,6 @@ abstract class AbstractBot { this.orderCount++; this.logger.warn(`${this.instanceName} Cancelling all outstanding orders, OrderNbr ${this.orderCount}`); const gasest = await this.getCancelAllOrdersGasEstimate(idsToCancel); - await this.correctNonce(this.contracts["SubNetProvider"]); const tx = await this.tradePair.cancelOrderList(idsToCancel, await this.getOptions(this.contracts["SubNetProvider"], gasest)); //const tx = await this.race({ promise:oderCancel , count: this.orderCount} ); @@ -1272,7 +1277,7 @@ abstract class AbstractBot { setTimeout(async()=>{ await this.correctNonce(this.contracts["SubNetProvider"]); this.cancelOrderList(orderIds); - },2000); + },1000); } } diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index d5eed42..ef5a68e 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -1,6 +1,7 @@ import MarketMakerBot from "./MarketMakerBot"; +import MarketMakerBotOrderLists from "./MarketMakerBotOrderLists"; import TakerBot from "./TakerBot"; -const Bot:any = {marketMaker: MarketMakerBot, taker:TakerBot}; +const Bot:any = {marketMaker: MarketMakerBot, marketMakerLists: MarketMakerBotOrderLists, taker:TakerBot}; module.exports = { createBot(type:any, attributes:any) { diff --git a/services/bots/MarketMakerBotOrderLists.ts b/services/bots/MarketMakerBotOrderLists.ts new file mode 100644 index 0000000..bbe79ee --- /dev/null +++ b/services/bots/MarketMakerBotOrderLists.ts @@ -0,0 +1,454 @@ +import axios from "axios"; +import { getConfig } from "../../config"; +import utils from "../utils"; +import BigNumber from "bignumber.js"; +import AbstractBot from "./AbstractBot"; +import NewOrder from "./classes"; + +class MarketMakerBot extends AbstractBot { + protected marketPrice = new BigNumber(0); + protected baseUsd = 0; + protected quoteUsd = 0; + protected capitalASideUSD = 300; + protected orderUpdaterCounter = 0; + protected lastMarketPrice = new BigNumber(0); + protected bidSpread: any; + protected askSpread: any; + protected orderLevels: any; + protected orderLevelSpread: any; + protected orderLevelQty: any; + protected refreshOrderTolerance: any; + protected flatAmount: any; + protected timer: any; + protected lastBaseUsd: any; + protected lastUpdate: any; + + constructor(botId: number, pairStr: string, privateKey: string) { + super(botId, pairStr, privateKey); + // Will try to rebalance the amounts in the Portfolio Contract + this.portfolioRebalanceAtStart = false; + this.config = getConfig(this.tradePairIdentifier); + this.bidSpread = this.config.bidSpread/100; + this.askSpread = this.config.askSpread/100; + this.orderLevels = this.config.orderLevels; + this.orderLevelSpread = this.config.orderLevelSpread/100; + this.orderLevelQty = this.config.orderLevelQty; + this.refreshOrderTolerance = this.config.refreshOrderTolerance/100; + this.flatAmount = this.config.flatAmount; + } + + async saveBalancestoDb(balancesRefreshed: boolean): Promise { + this.logger.info(`${this.instanceName} Save Balances somewhere if needed`); + } + + async initialize(): Promise { + const initializing = await super.initialize(); + if (initializing) { + await this.getNewMarketPrice(); + // await this.getBestOrders(); + + this.interval = 15000; //Min 10 seconds + + // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc + //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); + + return true; + } else { + return false; + } + } + + async startOrderUpdater() { + if (this.status) { + // Sleep 30 seconds initially if rebalancing portfolio + if (this.portfolioRebalanceAtStart){ + await utils.sleep(30000); + } + + this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); + + await this.correctNonce(this.contracts["SubNetProvider"]); + //Cancel any remaining orders + await this.cancelOrderList([], 100); + + if (this.baseUsd && this.quoteUsd){ + // ------------ Create and Send Initial Order List ------------ // + let levels : number[][] = []; + for (let i = 1; i <= this.orderLevels; i++){ + levels.push([0,i]); + levels.push([1,i]); + } + await this.getBestOrders(); + await this.placeInitialOrders(levels); + + // ------------ Begin Order Updater ------------ // + + this.orderUpdater = setTimeout(()=>{ + this.lastMarketPrice = this.marketPrice; + this.updateOrders(); + }, this.interval); + } else { + console.log("MISSING PRICE DATA - baseUsd:",this.baseUsd, " quoteUsd: ",this.quoteUsd, "Wait 10 seconds then try again"); + await utils.sleep(10000); + await this.getNewMarketPrice(); + this.startOrderUpdater(); + } + } else { + this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); + } + } + + async updateOrders() { + if (this.orderUpdater != undefined) { + clearTimeout(this.orderUpdater); + } + + try { + console.log(Date.now(), this.lastUpdate) + if (this.status && ((Date.now() - this.lastUpdate)/1000 > 20 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ + this.orderUpdaterCounter ++; + this.lastUpdate = Date.now(); + this.timer = this.interval; + console.log("000000000000000 COUNTER:",this.orderUpdaterCounter); + + // having issues with nonces when avax/usdc and avax/usdt send orders at the same time. This gives priority to avaxusdc + if (this.tradePairIdentifier == "AVAX/USDt"){ + await utils.sleep(500); + } + + await Promise.all([this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders(),this.getBalances(),this.getBestOrders()]); + const promise = Promise.resolve(this.cancelOrderList([], 100)); + if (this.baseUsd && this.quoteUsd){ + // ------------ Create and Send Initial Order List ------------ // + let levels : number[][] = []; + for (let i = 1; i <= this.orderLevels; i++){ + levels.push([0,i]); + levels.push([1,i]); + } + + let bids: any[] = []; + let asks: any[] = []; + let duplicates: any[] = []; + + this.orders.forEach((e,i)=>{ + if (e.side === 0 && e.level > 0 && (e.status == 0 || e.status == 2)){ + let skip = false; + for (let i = 0;i 0 && (e.status == 0 || e.status == 2)) { + let skip = false; + for (let i = 0;i{ + await this.correctNonce(this.contracts["SubNetProvider"]) + await this.placeInitialOrders(levels, parseFloat(this.contracts[this.quote].portfolioAvail) + onBids, parseFloat(this.contracts[this.base].portfolioAvail) + onAsks); + }) + } + + this.lastMarketPrice = this.marketPrice; + } + } catch (error) { + this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); + this.cleanUpAndExit(); + } finally { + //Update orders again after interval + this.orderUpdater = setTimeout(async ()=>{ + if (this.status){ + await Promise.all([this.getNewMarketPrice()]); + this.timer = 2000; + this.updateOrders(); + } + }, this.timer); + } + } + + // Takes in an array of arrays. The first number of each subarray is the side, the second is the level. + // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList + async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ + + let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); + let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); + initialBidPrice = this.currentBestAsk && this.currentBestAsk <= initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; + initialAskPrice = this.currentBestBid && this.currentBestBid >= initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; + + let newOrderList : NewOrder[] = []; + // --------------- SET BIDS --------------- // + for (let x = 0; x < levels.length; x++){ + if (levels[x][0] == 0){ + let bidPrice = new BigNumber((initialBidPrice * (1-this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); + let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],availableQuote)); + if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + availableQuote -= bidQty.toNumber() * bidPrice.toNumber(); + console.log("BID LEVEL ",levels[x][1],": BID PRICE: ", bidPrice.toNumber(),", BID QTY: ",bidQty.toNumber(), "Portfolio Avail: ",availableQuote); + newOrderList.push(new NewOrder(0,bidQty,bidPrice,levels[x][1])); + } else { + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL BID: ", levels[x][1]) + } + } else { + //--------------- SET ASKS --------------- // + let askPrice = new BigNumber((initialAskPrice * (1+this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); + let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],availableBase)); + if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + availableBase -= askQty.toNumber(); + console.log("ASK LEVEL ",levels[x][1],": ASK PRICE: ", askPrice.toNumber(),", ASK QTY: ",askQty.toNumber(), "Portfolio Avail: ",availableBase); + newOrderList.push(new NewOrder(1,askQty,askPrice,levels[x][1])); + } else { + console.log("NOT ENOUGH FUNDS TO PLACE INITIAL ASK: ", levels[x][1]) + } + } + } + + + // // --------------- EXECUTE ORDERS --------------- // + if (newOrderList.length == 0){ + console.log("ERROR - NewOrderList empty"); + } else if (newOrderList.length == 1){ + if (this.status){ + this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); + } + } else { + if (this.status){ + console.log("PLACING INITAL ORDERS: ",levels); + this.addLimitOrderList(newOrderList); + } + } + + this.lastUpdate = Date.now(); + } + + async replaceBids(bidsSorted: any, startingBidPrice: number){ + console.log("REPLACE BIDS: ",bidsSorted.length); + let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); + for (let i = 0; i < this.orderLevels; i ++){ + let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; + for (let j = 0; j < bidsSorted.length; j++){ + if (bidsSorted[j].level == i+1){ + order = bidsSorted[j]; + } + } + + if (order.id){ + let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.999; + let availableFunds = quoteAvail + amountOnOrder; + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); + let amountToPlace = bidQty; + if (availableFunds/bidPrice.toNumber() < amountToPlace.toNumber()){ + amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); + } + if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + console.log("REPLACE ORDER:",amountToPlace.toNumber(),bidQty.toNumber(), i+1); + quoteAvail -= bidQty.toNumber() * bidPrice.toNumber() - amountOnOrder + this.cancelReplaceOrder(order,bidPrice,amountToPlace); + } else { + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), quoteAvail, availableFunds, amountOnOrder, amountToPlace.toNumber()); + this.cancelOrder(order); + } + } else { + //set aside funds to create new orders + let amount = this.getLevelQty(i+1) * startingBidPrice; + if (amount < quoteAvail){ + quoteAvail -= amount; + this.placeInitialOrders([[0,i+1]],amount,); + } else { + this.placeInitialOrders([[0,i+1]],quoteAvail,); + quoteAvail = 0; + } + } + } + } + + async replaceAsks (asksSorted: any, startingAskPrice: number){ + console.log("REPLACE ASKS: ",asksSorted.length); + let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); + + for (let i = 0; i < this.orderLevels; i ++){ + let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; + for (let j = 0; j < asksSorted.length; j++){ + if (asksSorted[j].level == i+1){ + order = asksSorted[j]; + } + } + if (order.id){ + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .999; + let availableFunds = baseAvail + amountOnOrder; + + let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); + let amountToPlace = askQty; + if (availableFunds < askQty.toNumber()){ + amountToPlace = new BigNumber(availableFunds * .999); + } + baseAvail -= askQty.toNumber() - amountOnOrder; + if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + console.log("REPLACE ORDER:",askPrice.toNumber(),amountToPlace.toNumber(), i+1); + this.cancelReplaceOrder(order,askPrice,amountToPlace); + } else { + console.log("NOT ENOUGH FUNDS TO REPLACE", amountToPlace.toNumber(), availableFunds); + this.cancelOrder(order); + } + } else { + let amount = this.getLevelQty(i+1) * 1.01; + if (amount < baseAvail){ + this.placeInitialOrders([[1,i+1]],undefined,amount); + baseAvail -= amount; + } else { + this.placeInitialOrders([[1,i+1]],undefined,baseAvail); + baseAvail = 0; + } + } + } + } + + // Takes in price, side, level, and availableFunds. Returns amount to place. + // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 + getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { + if (side === 0){ + console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + if (this.getLevelQty(level) < availableFunds/price.toNumber()){ + return this.getLevelQty(level); + } else if (availableFunds > this.minTradeAmnt * 2){ + return availableFunds/price.toNumber() * .999; + } else { return 0;} + } else if (side === 1) { + console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) + if (this.getLevelQty(level) < availableFunds){ + return this.getLevelQty(level); + } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ + return availableFunds * .999; + } else {return 0;} + } else { + return 0; // function declaration requires I return a number + } + } + + getLevelQty(level:number):number{ + return parseFloat(this.flatAmount) + (parseFloat(this.orderLevelQty) * (level-1)); + } + + getSpread(level:number):number{ + return (level*parseFloat(this.orderLevelSpread)) + } + + // Update the marketPrice from an outside source + async getNewMarketPrice() { + try { + let response = await axios.get('http://localhost:3000/prices'); + let prices = response.data; + + + if (this.base == "sAVAX"){ + this.quoteUsd = prices[this.quote+'-USD']; + this.baseUsd = prices['sAVAX-AVAX'] * this.quoteUsd; + } else { + this.baseUsd = prices[this.base+'-USD']; + this.quoteUsd = prices[this.quote+'-USD']; + } + if (this.baseUsd && this.quoteUsd){ + this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); + console.log("new market Price:",this.marketPrice.toNumber()); + } else { + throw 'trouble getting base or quote prices' + } + } catch (error: any) { + this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); + } + return this.marketPrice; + } + + getPrice(side: number): BigNumber { + return this.marketPrice; + } + + async getAlotPrice(): Promise { + let alotprice = 0.25; + try { + alotprice = 0.25; // FIXME Implement your own price source to get the ALOT price + } catch (error) { + this.logger.error(`${this.instanceName} Error during getAlotPrice`, error); + } + return alotprice; + } + + getBaseCapital(): number { + if (this.baseUsd) { + return parseFloat((this.capitalASideUSD / this.baseUsd).toFixed(this.baseDisplayDecimals)); + } else { + return this.initialDepositBase; + } + } + + getQuoteCapital(): number { + if (this.quoteUsd) { + return parseFloat((this.capitalASideUSD / this.quoteUsd).toFixed(this.quoteDisplayDecimals)); + } else { + return this.initialDepositQuote; + } + } + + getIncrement(): number { + let increment = '0.'; + for (let i = 0; i < this.quoteDisplayDecimals; i++){ + if (i < this.quoteDisplayDecimals - 1){ + increment += '0' + } else { + increment += '1' + } + } + return parseFloat(increment); + } + +} + +const sortOrders = (arr: any, propertyName: any, order: string = 'ascending') => { + const sortedArr = arr.sort((a: any, b: any) => { + if (a[propertyName] < b[propertyName]) { + return -1; + } + if (a[propertyName] > b[propertyName]) { + return 1; + } + return 0; + }); + + if (order === 'descending') { + return sortedArr.reverse(); + } + + return sortedArr; +}; + +export default MarketMakerBot; From d66129fbdfa4da676d748753c8c227fe85b8e3b2 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 25 Aug 2023 11:52:05 +0700 Subject: [PATCH 087/173] remove filepath file and comment out reference in abstract bot --- filePath | 1 - services/bots/AbstractBot.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 filePath diff --git a/filePath b/filePath deleted file mode 100644 index e21b88f..0000000 --- a/filePath +++ /dev/null @@ -1 +0,0 @@ -{nonce:13421} \ No newline at end of file diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 581667d..03b8780 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -902,7 +902,7 @@ abstract class AbstractBot { } async correctNonce(provider: any) { - let filePath = path.join(__dirname, './nonce.json'); + // let filePath = path.join(__dirname, './nonce.json'); try { const expectedNonce = await provider.provider.getTransactionCount(this.account); provider.nonce = expectedNonce; From 86860567f6e86fa4cdb71b2a8b731389958448ab Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 25 Aug 2023 12:05:09 +0700 Subject: [PATCH 088/173] remove lastnonce --- services/bots/AbstractBot.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 03b8780..be91e10 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -72,7 +72,6 @@ abstract class AbstractBot { protected currentBestBid: any; protected currentBestAsk: any; protected counter: any; - protected lastNonce: any; constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { this.logger = getLogger("Bot"); @@ -803,7 +802,7 @@ abstract class AbstractBot { const gasLimit = Math.min(gasEstimate.mul(120).div(100).toNumber(), 30000000); // Block Gas Limit 30M const optionsWithNonce = { gasLimit, maxFeePerGas, maxPriorityFeePerGas: 1, nonce: 0 }; - optionsWithNonce.nonce = this.lastNonce++; + optionsWithNonce.nonce = provider.nonce++; return optionsWithNonce; } @@ -906,9 +905,6 @@ abstract class AbstractBot { try { const expectedNonce = await provider.provider.getTransactionCount(this.account); provider.nonce = expectedNonce; - if (provider == this.contracts["SubNetProvider"]){ - this.lastNonce = provider.nonce; - } } catch (error) { //this.logger.error(`${this.instanceName} 'Error during nonce correction`, error); } From 396055c0a5b9b40e611249376630848b1d1fa146 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 25 Aug 2023 12:23:41 +0700 Subject: [PATCH 089/173] hardcode gas allowance for cancelreplace --- services/bots/AbstractBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index be91e10..a3ab277 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1399,7 +1399,7 @@ abstract class AbstractBot { console.log("CANCEL REPLACE: New clientOrderid: ", clientOrderId," PRICE:", price.toNumber(), " QTY: ", quantity.toNumber()); - const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); + //const gasest = await this.getCancelReplaceOrderGasEstimate(order.id, clientOrderId ,priceToSend, quantityToSend); //console.log("CANCEL REPLACE: GOT GASEST"); @@ -1410,7 +1410,7 @@ abstract class AbstractBot { order.side === 0 ? "BUY" : "SELL" } ::: ${quantity.toString()} ${this.base} @ ${price.toString()} ${this.quote}` ); - const options = await this.getOptions(this.contracts["SubNetProvider"], gasest); + const options = await this.getOptions(this.contracts["SubNetProvider"], BigNumberEthers.from(1200000)); const tx = await this.tradePair.cancelReplaceOrder(order.id, clientOrderId, priceToSend, quantityToSend, options); const orderLog = await tx.wait(); From 96aa9ad7dabc412a515dd9c2497b5a8a8fbf377d Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 4 Sep 2023 21:59:19 +0700 Subject: [PATCH 090/173] add taker option --- services/bots/MarketMakerBot.ts | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9924481..da6f2a9 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -19,6 +19,8 @@ class MarketMakerBot extends AbstractBot { protected orderLevelQty: any; protected refreshOrderTolerance: any; protected flatAmount: any; + protected takerSpread: any; + protected takerEnabled: any; protected timer: any; protected lastBaseUsd: any; protected lastUpdate: any; @@ -35,6 +37,8 @@ class MarketMakerBot extends AbstractBot { this.orderLevelQty = this.config.orderLevelQty; this.refreshOrderTolerance = this.config.refreshOrderTolerance/100; this.flatAmount = this.config.flatAmount; + this.takerSpread = this.config.takerSpread/100; + this.takerEnabled = this.config.takerEnabled; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -47,7 +51,7 @@ class MarketMakerBot extends AbstractBot { await this.getNewMarketPrice(); // await this.getBestOrders(); - this.interval = 15000; //Min 10 seconds + this.interval = 30000; //Min 10 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -117,6 +121,8 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); let startingBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); let startingAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); + let takerBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.takerSpread)).toFixed(this.quoteDisplayDecimals)); + let takerAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.takerSpread)).toFixed(this.quoteDisplayDecimals)); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; @@ -167,25 +173,43 @@ class MarketMakerBot extends AbstractBot { let asksSorted = sortOrders(asks, "price", "ascending"); - - if (currentBestAsk && startingBidPrice > currentBestAsk){ + // if takerEnabled is true and best orders are outside of the takerspread, create an immediate or cancel order at the taker price. Otherwise replace orders as usual. + if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk) { + await this.cancelOrderList([]); + let bidAmount = new BigNumber((this.contracts[this.quote].portfolioTot / takerBidPrice) * .99); + let bidPrice = new BigNumber(takerBidPrice); + console.log("TAKER BUY,",bidAmount,"at: ",bidPrice); + await this.addOrder(0,bidAmount,bidPrice,1,2,0); + this.lastMarketPrice = new BigNumber(0); + + } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid){ + await this.cancelOrderList([]); + let askAmount = new BigNumber((this.contracts[this.base].portfolioTot) * .99); + let askPrice = new BigNumber(takerAskPrice); + console.log("TAKER SELL,",askAmount,"at: ",askPrice); + await this.addOrder(1,askAmount,askPrice,1,2,0); + this.lastMarketPrice = new BigNumber(0); + + } else if (currentBestAsk && startingBidPrice > currentBestAsk){ console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) startingBidPrice = currentBestAsk - this.getIncrement(); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + this.lastMarketPrice = this.marketPrice; } else if (currentBestBid && startingAskPrice < currentBestBid){ console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) startingAskPrice = currentBestBid + this.getIncrement(); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + this.lastMarketPrice = this.marketPrice; } else { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + this.lastMarketPrice = this.marketPrice; } - this.lastMarketPrice = this.marketPrice; } } catch (error) { this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); From 7c177f9ce5897033737e501f1ee5ebd39618cfc9 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 4 Sep 2023 22:43:12 +0700 Subject: [PATCH 091/173] use max trade amount for taker trades if over max trade limit --- services/bots/MarketMakerBot.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index da6f2a9..9c309a5 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -176,7 +176,13 @@ class MarketMakerBot extends AbstractBot { // if takerEnabled is true and best orders are outside of the takerspread, create an immediate or cancel order at the taker price. Otherwise replace orders as usual. if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk) { await this.cancelOrderList([]); - let bidAmount = new BigNumber((this.contracts[this.quote].portfolioTot / takerBidPrice) * .99); + + let bidAmount: any = 0; + if ((this.contracts[this.quote].portfolioTot / takerBidPrice) > this.maxTradeAmnt){ + bidAmount = new BigNumber(this.maxTradeAmnt * .99); + } else { + bidAmount = new BigNumber((this.contracts[this.quote].portfolioTot / takerBidPrice) * .99); + } let bidPrice = new BigNumber(takerBidPrice); console.log("TAKER BUY,",bidAmount,"at: ",bidPrice); await this.addOrder(0,bidAmount,bidPrice,1,2,0); @@ -184,7 +190,13 @@ class MarketMakerBot extends AbstractBot { } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid){ await this.cancelOrderList([]); - let askAmount = new BigNumber((this.contracts[this.base].portfolioTot) * .99); + + let askAmount: any = 0; + if ((this.contracts[this.base].portfolioTot) > this.maxTradeAmnt){ + askAmount = new BigNumber(this.maxTradeAmnt * .99); + } else { + askAmount = new BigNumber(this.contracts[this.base].portfolioTot * .99); + } let askPrice = new BigNumber(takerAskPrice); console.log("TAKER SELL,",askAmount,"at: ",askPrice); await this.addOrder(1,askAmount,askPrice,1,2,0); From c7d9317e815bfb5315de3e3b3958c540144ff304 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 4 Sep 2023 22:50:08 +0700 Subject: [PATCH 092/173] use mintradeamount for taker trades --- services/bots/MarketMakerBot.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9c309a5..5697732 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -174,7 +174,7 @@ class MarketMakerBot extends AbstractBot { // if takerEnabled is true and best orders are outside of the takerspread, create an immediate or cancel order at the taker price. Otherwise replace orders as usual. - if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk) { + if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk && (this.contracts[this.quote].portfolioTot / takerBidPrice) > this.minTradeAmnt) { await this.cancelOrderList([]); let bidAmount: any = 0; @@ -188,11 +188,11 @@ class MarketMakerBot extends AbstractBot { await this.addOrder(0,bidAmount,bidPrice,1,2,0); this.lastMarketPrice = new BigNumber(0); - } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid){ + } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && this.contracts[this.base].portfolioTot > this.minTradeAmnt){ await this.cancelOrderList([]); let askAmount: any = 0; - if ((this.contracts[this.base].portfolioTot) > this.maxTradeAmnt){ + if (this.contracts[this.base].portfolioTot > this.maxTradeAmnt){ askAmount = new BigNumber(this.maxTradeAmnt * .99); } else { askAmount = new BigNumber(this.contracts[this.base].portfolioTot * .99); From 502ef71f25f1dcd2ce377b5029b1fc16cdf37e47 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 5 Sep 2023 17:45:14 +0700 Subject: [PATCH 093/173] lower interval back to 15 seconds --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 5697732..1752452 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -51,7 +51,7 @@ class MarketMakerBot extends AbstractBot { await this.getNewMarketPrice(); // await this.getBestOrders(); - this.interval = 30000; //Min 10 seconds + this.interval = 15000; //Min 10 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); From 301b877ffa6780c6828ca8a8c82ca1533e90f703 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 5 Sep 2023 17:54:57 +0700 Subject: [PATCH 094/173] fix lastupdate variable in marketmakerbot --- services/bots/MarketMakerBot.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 1752452..4c34aa7 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -39,6 +39,7 @@ class MarketMakerBot extends AbstractBot { this.flatAmount = this.config.flatAmount; this.takerSpread = this.config.takerSpread/100; this.takerEnabled = this.config.takerEnabled; + this.lastUpdate = 0; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -107,7 +108,7 @@ class MarketMakerBot extends AbstractBot { } try { - if (this.status && ((Date.now() - this.lastUpdate)/1000 > 900 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ + if (this.status && ((Date.now() - this.lastUpdate)/1000 > 600 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ this.orderUpdaterCounter ++; this.lastUpdate = Date.now(); this.timer = this.interval; From 5ff4f846b691afd7da972ab2a4f101eb2734d1cc Mon Sep 17 00:00:00 2001 From: beastlorion Date: Wed, 6 Sep 2023 12:01:42 +0700 Subject: [PATCH 095/173] fix taker bid amount --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 4c34aa7..9991d99 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -180,7 +180,7 @@ class MarketMakerBot extends AbstractBot { let bidAmount: any = 0; if ((this.contracts[this.quote].portfolioTot / takerBidPrice) > this.maxTradeAmnt){ - bidAmount = new BigNumber(this.maxTradeAmnt * .99); + bidAmount = new BigNumber((this.maxTradeAmnt / takerBidPrice) * .99); } else { bidAmount = new BigNumber((this.contracts[this.quote].portfolioTot / takerBidPrice) * .99); } From 68a8f0b048d436c20b0ac8008c40de1c2d94402f Mon Sep 17 00:00:00 2001 From: beastlorion Date: Wed, 6 Sep 2023 21:10:28 +0700 Subject: [PATCH 096/173] parsefloat for portfoliotot --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9991d99..2af4ba2 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -175,7 +175,7 @@ class MarketMakerBot extends AbstractBot { // if takerEnabled is true and best orders are outside of the takerspread, create an immediate or cancel order at the taker price. Otherwise replace orders as usual. - if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk && (this.contracts[this.quote].portfolioTot / takerBidPrice) > this.minTradeAmnt) { + if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk && (parseFloat(this.contracts[this.quote].portfolioTot) / takerBidPrice) > this.minTradeAmnt) { await this.cancelOrderList([]); let bidAmount: any = 0; @@ -189,7 +189,7 @@ class MarketMakerBot extends AbstractBot { await this.addOrder(0,bidAmount,bidPrice,1,2,0); this.lastMarketPrice = new BigNumber(0); - } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && this.contracts[this.base].portfolioTot > this.minTradeAmnt){ + } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && parseFloat(this.contracts[this.base].portfolioTot) > this.minTradeAmnt){ await this.cancelOrderList([]); let askAmount: any = 0; From 0de363dc6a5e8ff734126006af6a707c782cfa2c Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 8 Sep 2023 22:16:46 +0700 Subject: [PATCH 097/173] fix maxtradeamount calculation for taker trades --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 2af4ba2..e1c7a93 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -193,8 +193,8 @@ class MarketMakerBot extends AbstractBot { await this.cancelOrderList([]); let askAmount: any = 0; - if (this.contracts[this.base].portfolioTot > this.maxTradeAmnt){ - askAmount = new BigNumber(this.maxTradeAmnt * .99); + if (this.contracts[this.base].portfolioTot * takerAskPrice > this.maxTradeAmnt){ + askAmount = new BigNumber(this.maxTradeAmnt / takerAskPrice * .99); } else { askAmount = new BigNumber(this.contracts[this.base].portfolioTot * .99); } From afbc4165ae5df3a876beb2aa475c235ecbdae69c Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 11 Sep 2023 23:25:04 +0700 Subject: [PATCH 098/173] add try catch to get revert reason --- services/bots/AbstractBot.ts | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index a3ab277..3ab2429 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -775,25 +775,30 @@ abstract class AbstractBot { } async getRevertReason(error: any, provider: any = this.contracts["SubNetProvider"]) { - let reason; - const idx = error.message.indexOf("VM Exception while processing transaction: reverted "); - if (idx > -1) { - //Hardhat revert reason already in the message - return error.message.substring(idx + 72, idx + 81); - } else { - if (!error.transaction) { - this.logger.warn(`${this.instanceName} getRevertReason: error.transaction is undefined`); + try{ + let reason; + const idx = error.message.indexOf("VM Exception while processing transaction: reverted "); + if (idx > -1) { + //Hardhat revert reason already in the message + return error.message.substring(idx + 72, idx + 81); } else { - //https://gist.github.com/gluk64/fdea559472d957f1138ed93bcbc6f78a - const code = await provider.provider.call(error.transaction, error.blockNumber); - reason = ethers.utils.toUtf8String("0x" + code.substr(138)); - const i = reason.indexOf("\0"); // delete all null characters after the string - if (i > -1) { - return reason.substring(0, i); + if (!error.transaction) { + this.logger.warn(`${this.instanceName} getRevertReason: error.transaction is undefined`); + } else { + //https://gist.github.com/gluk64/fdea559472d957f1138ed93bcbc6f78a + const code = await provider.provider.call(error.transaction, error.blockNumber); + reason = ethers.utils.toUtf8String("0x" + code.substr(138)); + const i = reason.indexOf("\0"); // delete all null characters after the string + if (i > -1) { + return reason.substring(0, i); + } } } + return reason; + } catch { + return "Unable to find reason for revert"; } - return reason; + } async getOptions(provider: any = this.contracts["SubNetProvider"], gasEstimate: BigNumberEthers = BigNumberEthers.from(1000000)) { From 982a7d2a702975b3e0b73e53e7a65755fc7b11bd Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 18 Sep 2023 15:29:36 +0700 Subject: [PATCH 099/173] fix typo in replacebids inputs --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index e1c7a93..0774841 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -215,7 +215,7 @@ class MarketMakerBot extends AbstractBot { console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) startingAskPrice = currentBestBid + this.getIncrement(); - await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + await Promise.all([this.replaceBids(bidsSorted, startingAskPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; } else { From 6c802708b8505801a2653458003cc48a802c2b6a Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 18 Sep 2023 15:59:03 +0700 Subject: [PATCH 100/173] rounding away from market price to avoid post only errors --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 0774841..a27f76f 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -206,14 +206,14 @@ class MarketMakerBot extends AbstractBot { } else if (currentBestAsk && startingBidPrice > currentBestAsk){ console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) - startingBidPrice = currentBestAsk - this.getIncrement(); + startingBidPrice = Math.floor((currentBestAsk - this.getIncrement())*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; } else if (currentBestBid && startingAskPrice < currentBestBid){ console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) - startingAskPrice = currentBestBid + this.getIncrement(); + startingAskPrice = Math.ceil((currentBestBid + this.getIncrement())*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals); await Promise.all([this.replaceBids(bidsSorted, startingAskPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; From 0f040c7e9d384a6dacf8771d18601691746e4551 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 18 Sep 2023 16:24:08 +0700 Subject: [PATCH 101/173] add rounding for starting prices --- services/bots/MarketMakerBot.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index a27f76f..cfb6a77 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -121,7 +121,9 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); let startingBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); + startingBidPrice = Math.floor(startingBidPrice*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals) let startingAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); + startingAskPrice = Math.ceil(startingAskPrice*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals) let takerBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.takerSpread)).toFixed(this.quoteDisplayDecimals)); let takerAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.takerSpread)).toFixed(this.quoteDisplayDecimals)); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; From 06960c6e755d2290962c9d342e0c7b7215ae9bee Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 18 Sep 2023 16:29:04 +0700 Subject: [PATCH 102/173] adjust comparisons to avoid post only errors --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index cfb6a77..b088ff8 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -205,7 +205,7 @@ class MarketMakerBot extends AbstractBot { await this.addOrder(1,askAmount,askPrice,1,2,0); this.lastMarketPrice = new BigNumber(0); - } else if (currentBestAsk && startingBidPrice > currentBestAsk){ + } else if (currentBestAsk && startingBidPrice >= currentBestAsk){ console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) startingBidPrice = Math.floor((currentBestAsk - this.getIncrement())*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals); @@ -213,7 +213,7 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; - } else if (currentBestBid && startingAskPrice < currentBestBid){ + } else if (currentBestBid && startingAskPrice <= currentBestBid){ console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) startingAskPrice = Math.ceil((currentBestBid + this.getIncrement())*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals); From bd3ba49ae9198b20932783b484be34a75f06b1a9 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 21 Sep 2023 16:11:03 +0700 Subject: [PATCH 103/173] fix rounding order prices --- services/bots/MarketMakerBot.ts | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index b088ff8..2e7c53a 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -120,14 +120,15 @@ class MarketMakerBot extends AbstractBot { } await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); - let startingBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); - startingBidPrice = Math.floor(startingBidPrice*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals) - let startingAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); - startingAskPrice = Math.ceil(startingAskPrice*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals) + let startingBidPriceBG = this.marketPrice.multipliedBy(1-this.bidSpread).dp(this.quoteDisplayDecimals, BigNumber.ROUND_DOWN); + let startingBidPrice = startingBidPriceBG.toNumber(); + let startingAskPriceBG = this.marketPrice.multipliedBy(1+this.askSpread).dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP); + let startingAskPrice = startingAskPriceBG.toNumber(); let takerBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.takerSpread)).toFixed(this.quoteDisplayDecimals)); let takerAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.takerSpread)).toFixed(this.quoteDisplayDecimals)); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; + console.log("Starting Bid Price:",startingBidPrice,"Starting Ask Price:", startingAskPrice); let bids: any[] = []; let asks: any[] = []; @@ -206,16 +207,16 @@ class MarketMakerBot extends AbstractBot { this.lastMarketPrice = new BigNumber(0); } else if (currentBestAsk && startingBidPrice >= currentBestAsk){ - console.log("BEST ASK: ",currentBestAsk, "STARTING BID PRICE: ", startingBidPrice) - startingBidPrice = Math.floor((currentBestAsk - this.getIncrement())*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals); + let startingBidPriceBG = new BigNumber(currentBestAsk - this.getIncrement()) + startingBidPrice = startingBidPriceBG.dp(this.quoteDisplayDecimals,BigNumber.ROUND_DOWN).toNumber(); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; } else if (currentBestBid && startingAskPrice <= currentBestBid){ - console.log("BEST BID: ",currentBestBid, "STARTING ASK PRICE: ", startingAskPrice) - startingAskPrice = Math.ceil((currentBestBid + this.getIncrement())*Math.pow(10,this.quoteDisplayDecimals))/Math.pow(10,this.quoteDisplayDecimals); + let startingAskPriceBG = new BigNumber(currentBestBid + this.getIncrement()) + startingAskPrice = startingAskPriceBG.dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP).toNumber(); await Promise.all([this.replaceBids(bidsSorted, startingAskPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; @@ -280,7 +281,6 @@ class MarketMakerBot extends AbstractBot { // // --------------- EXECUTE ORDERS --------------- // if (newOrderList.length == 0){ - console.log("ERROR - NewOrderList empty"); } else if (newOrderList.length == 1){ if (this.status){ this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); @@ -463,15 +463,8 @@ class MarketMakerBot extends AbstractBot { } getIncrement(): number { - let increment = '0.'; - for (let i = 0; i < this.quoteDisplayDecimals; i++){ - if (i < this.quoteDisplayDecimals - 1){ - increment += '0' - } else { - increment += '1' - } - } - return parseFloat(increment); + let increment = 1 / (Math.pow(10,this.quoteDisplayDecimals)); + return increment; } } From 3de037a8088e18e9d7c7b3d86c9af2f37bcc8e58 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 21 Sep 2023 16:24:41 +0700 Subject: [PATCH 104/173] adjust ask price by minimum increment if same as bid price --- services/bots/MarketMakerBot.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 2e7c53a..ff31401 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -124,6 +124,11 @@ class MarketMakerBot extends AbstractBot { let startingBidPrice = startingBidPriceBG.toNumber(); let startingAskPriceBG = this.marketPrice.multipliedBy(1+this.askSpread).dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP); let startingAskPrice = startingAskPriceBG.toNumber(); + + if (startingBidPrice == startingAskPrice){ + startingAskPrice += this.getIncrement(); + } + let takerBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.takerSpread)).toFixed(this.quoteDisplayDecimals)); let takerAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.takerSpread)).toFixed(this.quoteDisplayDecimals)); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; From 052670875b6b985adb595dd07492d7b8e34f6f8c Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 21 Sep 2023 17:01:24 +0700 Subject: [PATCH 105/173] fix replacebids price --- services/bots/MarketMakerBot.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index ff31401..6b9f33a 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -133,7 +133,6 @@ class MarketMakerBot extends AbstractBot { let takerAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.takerSpread)).toFixed(this.quoteDisplayDecimals)); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; - console.log("Starting Bid Price:",startingBidPrice,"Starting Ask Price:", startingAskPrice); let bids: any[] = []; let asks: any[] = []; @@ -223,7 +222,7 @@ class MarketMakerBot extends AbstractBot { let startingAskPriceBG = new BigNumber(currentBestBid + this.getIncrement()) startingAskPrice = startingAskPriceBG.dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP).toNumber(); - await Promise.all([this.replaceBids(bidsSorted, startingAskPrice),this.replaceAsks(asksSorted, startingAskPrice)]); + await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; } else { @@ -298,7 +297,7 @@ class MarketMakerBot extends AbstractBot { } async replaceBids(bidsSorted: any, startingBidPrice: number){ - console.log("REPLACE BIDS: ",bidsSorted.length); + console.log("REPLACE BIDS: ",bidsSorted.length, "startingBidPrice:", startingBidPrice); let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); for (let i = 0; i < this.orderLevels; i ++){ let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; @@ -318,7 +317,7 @@ class MarketMakerBot extends AbstractBot { amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); } if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - console.log("REPLACE ORDER:",amountToPlace.toNumber(),bidQty.toNumber(), i+1); + console.log("REPLACE ORDER:",bidPrice.toNumber(),bidQty.toNumber(), i+1); quoteAvail -= bidQty.toNumber() * bidPrice.toNumber() - amountOnOrder this.cancelReplaceOrder(order,bidPrice,amountToPlace); } else { @@ -340,7 +339,7 @@ class MarketMakerBot extends AbstractBot { } async replaceAsks (asksSorted: any, startingAskPrice: number){ - console.log("REPLACE ASKS: ",asksSorted.length); + console.log("REPLACE ASKS: ",asksSorted.length, "startingAskPrice:", startingAskPrice); let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); for (let i = 0; i < this.orderLevels; i ++){ From c5b07a2fda878c65220e37251af0e0912efb6d2a Mon Sep 17 00:00:00 2001 From: Beastlorion <90943050+Beastlorion@users.noreply.github.com> Date: Fri, 6 Oct 2023 11:40:29 -0500 Subject: [PATCH 106/173] Update README.md for customized_beastlorion Add documentation for MarketMakerBot and MarketMakerBotOrderLists --- README.md | 101 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index ac84ade..6447afb 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,75 @@ -## Sample Bot +## Beastlorion's Custom Dexalot Bots + +If you don't have nvm installed, follow the steps here: https://tecadmin.net/how-to-install-nvm-on-ubuntu-20-04/ + +## Setup: ``` +nvm install 16.15.1 +git checkout customized_beastlorion yarn install ``` -make sure to have the .env.fuji in the following. You can supply the private key encrypted or plain text +parameters are declared in .env.production for production or .env.fuji for testnet -{ - "bot_id" : "100", - "pair" : "AVAX/USDC", - "bot_type" : "SampleBot", - "private_key" : "51dda7beacb289d7eaaed575c3aeexxxxxxxxxxxxxx", - "account_no" : "0x051A4F2EBFb9d57D3655581xxxxxxxxxxxxx" +Paste this into your .env.fuji with your private key and address. PLEASE USE A TEST WALLET. +``` +{ "bot_id" : "100", +"bot_type" : "MarketMakerBot", +"private_key" : "xxx", +"account_no" : "xxx", +"rpc_url" : "", +"ENCYRPT_SECRET" : "secret", +"ENCRYPT_SALT" : "salt", +"AVAX/USDC" : + { + "bidSpread" : "0.3", + "askSpread" : "0.3", + "takerSpread" : "1.0", + "takerEnabled" : false, + "flatAmount" : "1", + "orderLevels" : "2", + "orderLevelSpread" : "0.30", + "orderLevelQty" : "0.5", + "refreshOrderTolerance" : "0.05" + } } +``` +To trade other markets(some are not active on the testnet), you will need to add objects for the tokens below the "AVAX/USDC" object. They are case sensitive. -You can get AVAX from fuji faucet and sell your avax against USDC at Dexalot Fuji at https://app.dexalot-test.com +Examples of other markets: + +``` +"AVAX/USDt" +"EUROC/USDC" +"USDt/USDC" +"WETH.e/USDC" +"BTC.b/USDC" +"sAVAX/AVAX" +``` +You can get AVAX from fuji faucet and sell your avax against USDC at Dexalot Fuji at https://app.dexalot-test.com if you need more USDC please contact the Dexalot Team. ## To run +NOTE: You will need to either start a price_feeds instance or another service to serve prices for the bot. You can also hardcode a price for testing purposes in getNewMarketPrice() +Fuji Testnet: ``` -yarn sampleBot-fuji +yarn marketMakerBot-fuji --pair="AVAX/USDC" ``` -## Flow +Production: +``` +yarn marketMakerBot-prod --pair="AVAX/USDC" +``` -This sample Bot extends the AbstractBot implementation. AbstractBot performs various functions: +## Abstract Class Flow +AbstractBot performs various functions: - Get the mainnet/subnet environments, pairs listed, token details from the RESTAPI - Create references to the necessary contracts -- Deposit initial amounts to the contract from the mainnet for trading (Note it takes about 30 seconds for the deposit to reach the subnet) +- (unused currently) Deposit initial amounts to the contract from the mainnet for trading (Note it takes about 30 seconds for the deposit to reach the subnet) - Requests open orders from the RESTAPI in case of crash recovery - Keeps a list of its outstanding orders, and a local orderbook in memory - Gets the best 2 bid/asks orderbook from the chain @@ -38,21 +77,39 @@ This sample Bot extends the AbstractBot implementation. AbstractBot performs var - it also captures OrderStatusChanged event as a part of tx results when sending an order and updates the order status in memory. The OrderStatusChanged event raised from the blockchain to all the listeners a few seconds later. So the same event is processed twice. Once when the order is sent out and again when it is received from the blockchain by the independent listener thread. -Hence it is normal to see the message "Duplicate Order event: ......" +(I've commented these messages out ->)Hence it is normal to see the message "Duplicate Order event: ......" - Double Checks the order status from the chain every 10 min, in case an OrderStatusChanged event is missed. +- When placing, replacing, or canceling orders, if there is an error, it may attempt to try again once or twice. + +## MarketMakerBot Flow +MarketMakerBot extends the AbstractBot implementation. It holds the main logic for the bot: +- Fetches prices for the chosen market from the price_feed bot in getNewMarketPrice() +- Places initial PostOnly Orders using addLimitOrderList() and starts the order updater loop. If the orderLevels config is > 1, it will attempt to add an additional bid and ask with increased quantity based on the orderLevelsQty config +- orderUpdater() will run if certain conditions are met. During initialization it will run. +- The interval variable determines how long to wait after executing orders before calling orderUpdater() again. If orderUpdater did not run, it will retrigger in a few seconds, after it fetches fresh data. +- If the conditions are met, it will refresh balances, get the best bid and ask prices, and refresh the nonce of the wallet. +- Next it checks for the order levels of the orders and sorts them. If there are duplicate records somehow, it will cancel the offending orders and they will be added again on the next loop. +- If the "marketTakerEnabled" config == true AND the best bid or ask is passed the price threshold "takerSpread" config, it will trigger an "immediate or cancel" trade at marketPrice * (1 +/- takerSpread) +- If the conditions for a taker trade are not met, it will begin refreshing the prices and quantities of the orders for the pair taking care to avoid PostOnly trade conflicts. +- When it is finished it will set a timer and then begin calling orderUpdater() again. + +## MarketMakerBotOrderLists (I don't use this so check it carefully before you use it) +This bot is an alternative to MarketMakerBot. The key difference is instead of replacing individual orders, it will cancel all of the active orders in one call, wait for confirmation, and then place all fresh orders in one call. + +Pros: +- Uses less calls/good for avoiding rate limitting. (If you're serious about this you'll want to start your own rpc node for unlimitted rpc calls.) +- The logic is much simpler and easier to understand. +Cons: +- Your orders will be off the books for about 8-12 seconds while it is waiting to get confirmation from transactions processing. -NOTE: -Sample Bot has hardcoded ALOT price in its getNewMarketPrice() function and will send orders using these hardcoded prices. - -Feel free to change the sampleBot and/or add a new bot type that extends AbstractBot. if it is a new bot , add it to the BotFactory.ts and the bot_type in the above .env.fuji file - ## TO DO - Listen to tradePairs' Executed event (trades) from the blockchain OR - Web Socket Connection to Dexalot APIs to receive the orderbook, and trades events instead of getting them from the blockchain. + Currently retrieves price feeds from another port on local host(which I'll add to a "price_feeds" repository). You may want to change how it calculates prices or where it fetches the prices from. ## DISCLAIMER -This bot is provided for facilitating the integration with Dexalot. It should not be used in PRODUCTION environments unless it is throughly tested. +I am sharing this bot for the benefit of Dexalot Exchange. It is still a work in progress. I will assume no responsibility for others using this. USE AT YOUR OWN RISK + +Good luck! :D From 3b70576b578c455d2471e0750bc7e9932fd9e705 Mon Sep 17 00:00:00 2001 From: Beastlorion <90943050+Beastlorion@users.noreply.github.com> Date: Fri, 6 Oct 2023 18:58:32 -0500 Subject: [PATCH 107/173] Update README.md --- README.md | 108 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index ac84ade..d164a7e 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,76 @@ -## Sample Bot +# Beastlorion's Custom Dexalot Bots +## Setup ``` +nvm install 16.15.1 yarn install ``` -make sure to have the .env.fuji in the following. You can supply the private key encrypted or plain text +You will need funds to trade. -{ - "bot_id" : "100", - "pair" : "AVAX/USDC", - "bot_type" : "SampleBot", - "private_key" : "51dda7beacb289d7eaaed575c3aeexxxxxxxxxxxxxx", - "account_no" : "0x051A4F2EBFb9d57D3655581xxxxxxxxxxxxx" +You can get AVAX from fuji faucet and sell your avax against USDC at Dexalot Fuji at https://app.dexalot-test.com +if you need more USDC please contact the Dexalot Team. + +config parameters are declared in .env.production for production or .env.fuji for testnet +Paste this into your .env.fuji with your private key and address. PLEASE USE A TEST WALLET. +For production, I recommend using a secrets manager for your wallet's private key for enhanced security. Also if you're using a remote server, which you probably should be, you should whitelist the IP that you will be connecting to it from. + +``` +{ "bot_id" : "100", +"bot_type" : "MarketMakerBot", +"private_key" : "xxx", +"account_no" : "xxx", +"rpc_url" : "", +"ENCYRPT_SECRET" : "secret", +"ENCRYPT_SALT" : "salt", +"AVAX/USDC" : + { + "bidSpread" : "0.3", + "askSpread" : "0.3", + "takerSpread" : "1.0", + "takerEnabled" : false, + "flatAmount" : "1", + "orderLevels" : "2", + "orderLevelSpread" : "0.30", + "orderLevelQty" : "0.5", + "refreshOrderTolerance" : "0.05" + } } +``` +To trade other markets(some are not active on the testnet), you will need to add objects for the tokens below the "AVAX/USDC" object. They are case sensitive. -You can get AVAX from fuji faucet and sell your avax against USDC at Dexalot Fuji at https://app.dexalot-test.com +Examples of other markets: -if you need more USDC please contact the Dexalot Team. +``` +"AVAX/USDt" +"EUROC/USDC" +"USDt/USDC" +"WETH.e/USDC" +"BTC.b/USDC" +"sAVAX/AVAX" +``` ## To run +- You will need to start a price_feeds instance which serves price data to a local port: (My price feeds: https://github.com/Beastlorion/dexalotBot_price_feeds) +- You can edit the price calculations there if you'd like. +- Once that is running on the same machine, run one of the following: +Fuji Testnet: ``` -yarn sampleBot-fuji +yarn marketMakerBot-fuji --pair="AVAX/USDC" ``` -## Flow +Production: +``` +yarn marketMakerBot-prod --pair="AVAX/USDC" +``` -This sample Bot extends the AbstractBot implementation. AbstractBot performs various functions: +## Abstract Class Flow +AbstractBot performs various functions: - Get the mainnet/subnet environments, pairs listed, token details from the RESTAPI - Create references to the necessary contracts -- Deposit initial amounts to the contract from the mainnet for trading (Note it takes about 30 seconds for the deposit to reach the subnet) +- (unused currently) Deposit initial amounts to the contract from the mainnet for trading (Note it takes about 30 seconds for the deposit to reach the subnet) - Requests open orders from the RESTAPI in case of crash recovery - Keeps a list of its outstanding orders, and a local orderbook in memory - Gets the best 2 bid/asks orderbook from the chain @@ -38,21 +78,35 @@ This sample Bot extends the AbstractBot implementation. AbstractBot performs var - it also captures OrderStatusChanged event as a part of tx results when sending an order and updates the order status in memory. The OrderStatusChanged event raised from the blockchain to all the listeners a few seconds later. So the same event is processed twice. Once when the order is sent out and again when it is received from the blockchain by the independent listener thread. -Hence it is normal to see the message "Duplicate Order event: ......" +(I've commented these messages out ->)Hence it is normal to see the message "Duplicate Order event: ......" - Double Checks the order status from the chain every 10 min, in case an OrderStatusChanged event is missed. - - -NOTE: -Sample Bot has hardcoded ALOT price in its getNewMarketPrice() function and will send orders using these hardcoded prices. - -Feel free to change the sampleBot and/or add a new bot type that extends AbstractBot. if it is a new bot , add it to the BotFactory.ts and the bot_type in the above .env.fuji file - -## TO DO - Listen to tradePairs' Executed event (trades) from the blockchain OR - Web Socket Connection to Dexalot APIs to receive the orderbook, and trades events instead of getting them from the blockchain. - +- When placing, replacing, or canceling orders, if there is an error, it may attempt to try again once or twice. + +## MarketMakerBot Flow +MarketMakerBot extends the AbstractBot implementation. It holds the main logic for the bot: +- Fetches prices for the chosen market from the price_feed bot in getNewMarketPrice() +- Places initial PostOnly Orders using addLimitOrderList() and starts the order updater loop. If the orderLevels config is > 1, it will attempt to add an additional bid and ask with increased quantity based on the orderLevelsQty config +- orderUpdater() will run if certain conditions are met. During initialization it will run. +- The interval variable determines how long to wait after executing orders before calling orderUpdater() again. If orderUpdater did not run, it will retrigger in a few seconds, after it fetches fresh data. +- If the conditions are met, it will refresh balances, get the best bid and ask prices, and refresh the nonce of the wallet. +- Next it checks for the order levels of the orders and sorts them. If there are duplicate records somehow, it will cancel the offending orders and they will be added again on the next loop. +- If the "marketTakerEnabled" config == true AND the best bid or ask is passed the price threshold "takerSpread" config, it will trigger an "immediate or cancel" trade at marketPrice * (1 +/- takerSpread) +- If the conditions for a taker trade are not met, it will begin refreshing the prices and quantities of the orders for the pair taking care to avoid PostOnly trade conflicts. +- When it is finished it will set a timer and then begin calling orderUpdater() again. + +## MarketMakerBotOrderLists (I don't use this so check it carefully before you use it) +This bot is an alternative to MarketMakerBot. The key difference is instead of replacing individual orders, it will cancel all of the active orders in one call, wait for confirmation, and then place all fresh orders in one call. + +Pros: +- Uses far fewer calls, which is good for avoiding rate limitting. (If you're serious about this you'll want to start your own rpc node for unlimitted rpc calls. You can add a custom rpc url to the config file) +- The logic is much simpler and easier to understand. +Cons: +- Your orders will be off the books for about 8-12 seconds while it is waiting to get confirmation from transactions processing. +- I don't actively use this version, so there may still be some bugs that need to be worked out. ## DISCLAIMER -This bot is provided for facilitating the integration with Dexalot. It should not be used in PRODUCTION environments unless it is throughly tested. +I am sharing this bot for free to encourage people to try providing liquidity for Dexalot Exchange. It is still a work in progress. I assume no responsibility for you or others using this. USE AT YOUR OWN RISK + +Good luck! :D From cb957dd256c44f70cd9b1d50aa7323c071b98297 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Fri, 6 Oct 2023 19:42:01 -0500 Subject: [PATCH 108/173] add comments, remove some deprecated variables, removed takerbot --- .gitignore | 3 +- services/bots/AbstractBot.ts | 12 +- services/bots/BotFactory.ts | 3 +- services/bots/MarketMakerBot.ts | 38 ++++-- services/bots/TakerBot.ts | 205 -------------------------------- 5 files changed, 30 insertions(+), 231 deletions(-) delete mode 100644 services/bots/TakerBot.ts diff --git a/.gitignore b/.gitignore index ceb32c2..9baf3d2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,4 @@ Procfile .env.* package-lock.json -/logs-* -/services/bots/nonce.json \ No newline at end of file +/logs-* \ No newline at end of file diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 3ab2429..28813bd 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -7,14 +7,11 @@ import { BlockchainContractType } from "../../models/BlockchainContractType"; import { BigNumber } from "bignumber.js"; import { BigNumber as BigNumberEthers } from "ethers"; import axios from "axios"; -import fs from "fs"; -import path from "path"; import { getLogger } from "../logger"; import OrderBook from "./orderbook"; import NewOrder from "./classes"; import ERC20ABI from "../../artifacts/contracts/ERC20.json"; -import savaxABI from "../../artifacts/contracts/savaxABI.json"; import OrderBookRecordRaw from "../../models/orderBookRecordRaw"; import OrderBookRaw from "../../models/orderBookRaw"; const apiUrl = getConfig("API_URL") + "privapi/trading/"; @@ -48,7 +45,7 @@ abstract class AbstractBot { protected filter: any; protected cleanupCalled = false; protected interval = 20000; - protected orderbook: any; //local orderbook to keep track of my own orders ONLY + protected orderbook: any; //local orderbook protected chainOrderbook: any; //orderbook from the chain protected orderUpdater: NodeJS.Timeout | undefined; protected rebalancePct = 0.9; @@ -68,7 +65,6 @@ abstract class AbstractBot { protected orderBooks: any; protected orderBookID: any; protected orderBookID1: any; - protected savaxContract: any; protected currentBestBid: any; protected currentBestAsk: any; protected counter: any; @@ -256,11 +252,6 @@ abstract class AbstractBot { this.tradePair = new ethers.Contract(deployment.address, deployment.abi.abi, this.contracts["SubnetWallet"]); this.contracts["TradePairs"].deployedContract = this.tradePair; - if (this.base == "sAVAX"){ - this.savaxContract = new ethers.Contract("0x2b2C81e08f1Af8835a78Bb2A90AE924ACE0eA4bE",savaxABI,this.contracts["MainnetWallet"]); - } - - this.minTradeAmnt = this.pairObject.mintrade_amnt; this.maxTradeAmnt = this.pairObject.maxtrade_amnt; this.quoteDisplayDecimals = this.pairObject.quotedisplaydecimals; @@ -408,7 +399,6 @@ abstract class AbstractBot { abstract saveBalancestoDb(balancesRefreshed: boolean): Promise; abstract getPrice(side: number): BigNumber; abstract getAlotPrice(): Promise; - // infinite loop that updates the order books periodically abstract startOrderUpdater(): Promise; abstract getBaseCapital(): number; abstract getQuoteCapital(): number; diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index ef5a68e..c1c0d76 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -1,7 +1,6 @@ import MarketMakerBot from "./MarketMakerBot"; import MarketMakerBotOrderLists from "./MarketMakerBotOrderLists"; -import TakerBot from "./TakerBot"; -const Bot:any = {marketMaker: MarketMakerBot, marketMakerLists: MarketMakerBotOrderLists, taker:TakerBot}; +const Bot:any = {marketMaker: MarketMakerBot, marketMakerLists: MarketMakerBotOrderLists}; module.exports = { createBot(type:any, attributes:any) { diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 6b9f33a..3a14e65 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -102,6 +102,7 @@ class MarketMakerBot extends AbstractBot { } } + // this is the meat and potatoes of the bot. It will repeatedly call itself to refresh orders if the price is outside the refreshOrderTolerance spread, or too much time has passed since the last update. async updateOrders() { if (this.orderUpdater != undefined) { clearTimeout(this.orderUpdater); @@ -114,21 +115,26 @@ class MarketMakerBot extends AbstractBot { this.timer = this.interval; console.log("000000000000000 COUNTER:",this.orderUpdaterCounter); - // having issues with nonces when avax/usdc and avax/usdt send orders at the same time. This gives priority to avaxusdc - if (this.tradePairIdentifier == "AVAX/USDt"){ - await utils.sleep(500); - } + // Uncomment the following when running both avax markets on the same wallet at the same time to avoid nonce errors because avax/usdc and avax/usdt tend to send orders at the same time. This gives priority to avaxusdc + // If you're serious about market making, you'll want to set up individual wallets for all of the high volatility markets to avoid nonce conflicts and other possible errors. + + // if (this.tradePairIdentifier == "AVAX/USDt"){ + // await utils.sleep(500); + // } + // updates balances, gets best bids and asks, and corrects the nonce await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); let startingBidPriceBG = this.marketPrice.multipliedBy(1-this.bidSpread).dp(this.quoteDisplayDecimals, BigNumber.ROUND_DOWN); let startingBidPrice = startingBidPriceBG.toNumber(); let startingAskPriceBG = this.marketPrice.multipliedBy(1+this.askSpread).dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP); let startingAskPrice = startingAskPriceBG.toNumber(); + // if the bid and ask are the same price, increase the ask by one tick if (startingBidPrice == startingAskPrice){ startingAskPrice += this.getIncrement(); } + // if takerEnabled config is true, these prices will be used to determine what price to place taker orders at. let takerBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.takerSpread)).toFixed(this.quoteDisplayDecimals)); let takerAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.takerSpread)).toFixed(this.quoteDisplayDecimals)); const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; @@ -138,6 +144,7 @@ class MarketMakerBot extends AbstractBot { let asks: any[] = []; let duplicates: any[] = []; + // cycles through all active orders in memory and sorts them into bids or asks. If they are duplicate records, cancel their corresponding orders. They will be replaced on the next loop. this.orders.forEach((e,i)=>{ if (e.side === 0 && e.level > 0 && (e.status == 0 || e.status == 2)){ let skip = false; @@ -182,7 +189,7 @@ class MarketMakerBot extends AbstractBot { // if takerEnabled is true and best orders are outside of the takerspread, create an immediate or cancel order at the taker price. Otherwise replace orders as usual. - if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk && (parseFloat(this.contracts[this.quote].portfolioTot) / takerBidPrice) > this.minTradeAmnt) { + if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk && (parseFloat(this.contracts[this.quote].portfolioTot) / takerBidPrice) > this.minTradeAmnt) { //taker bid await this.cancelOrderList([]); let bidAmount: any = 0; @@ -196,7 +203,7 @@ class MarketMakerBot extends AbstractBot { await this.addOrder(0,bidAmount,bidPrice,1,2,0); this.lastMarketPrice = new BigNumber(0); - } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && parseFloat(this.contracts[this.base].portfolioTot) > this.minTradeAmnt){ + } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && parseFloat(this.contracts[this.base].portfolioTot) > this.minTradeAmnt){ // taker ask await this.cancelOrderList([]); let askAmount: any = 0; @@ -210,7 +217,7 @@ class MarketMakerBot extends AbstractBot { await this.addOrder(1,askAmount,askPrice,1,2,0); this.lastMarketPrice = new BigNumber(0); - } else if (currentBestAsk && startingBidPrice >= currentBestAsk){ + } else if (currentBestAsk && startingBidPrice >= currentBestAsk){ // adjust prices if startingBidPrice is higher than the bestAsk. Then replace all orders. let startingBidPriceBG = new BigNumber(currentBestAsk - this.getIncrement()) startingBidPrice = startingBidPriceBG.dp(this.quoteDisplayDecimals,BigNumber.ROUND_DOWN).toNumber(); @@ -218,14 +225,14 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; - } else if (currentBestBid && startingAskPrice <= currentBestBid){ + } else if (currentBestBid && startingAskPrice <= currentBestBid){ // adjust prices if startingAskPrice is lower than the bestBid. Then replace all orders. let startingAskPriceBG = new BigNumber(currentBestBid + this.getIncrement()) startingAskPrice = startingAskPriceBG.dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP).toNumber(); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; - } else { + } else { // replace all orders await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; } @@ -296,6 +303,7 @@ class MarketMakerBot extends AbstractBot { } } + // This function loops through all of the bid orders and updates their corresponding orders and replaces missing orders. async replaceBids(bidsSorted: any, startingBidPrice: number){ console.log("REPLACE BIDS: ",bidsSorted.length, "startingBidPrice:", startingBidPrice); let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); @@ -338,6 +346,7 @@ class MarketMakerBot extends AbstractBot { } } + // This function loops through all of the ask orders and updates their corresponding orders and replaces missing orders. async replaceAsks (asksSorted: any, startingAskPrice: number){ console.log("REPLACE ASKS: ",asksSorted.length, "startingAskPrice:", startingAskPrice); let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); @@ -381,7 +390,7 @@ class MarketMakerBot extends AbstractBot { } // Takes in price, side, level, and availableFunds. Returns amount to place. - // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 + // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can. If there is not enough funds to place an order it will return 0 getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { if (side === 0){ console.log("AVAILABLE FUNDS IN QUOTE BID: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) @@ -402,15 +411,18 @@ class MarketMakerBot extends AbstractBot { } } + + // returns amount to place for given order level in base asset getLevelQty(level:number):number{ return parseFloat(this.flatAmount) + (parseFloat(this.orderLevelQty) * (level-1)); } + // returns % away from market price to place order getSpread(level:number):number{ return (level*parseFloat(this.orderLevelSpread)) } - // Update the marketPrice from an outside source + // Update the marketPrice from price feed bot async getNewMarketPrice() { try { let response = await axios.get('http://localhost:3000/prices'); @@ -436,6 +448,7 @@ class MarketMakerBot extends AbstractBot { return this.marketPrice; } + // not used getPrice(side: number): BigNumber { return this.marketPrice; } @@ -450,6 +463,7 @@ class MarketMakerBot extends AbstractBot { return alotprice; } + // NOT USED getBaseCapital(): number { if (this.baseUsd) { return parseFloat((this.capitalASideUSD / this.baseUsd).toFixed(this.baseDisplayDecimals)); @@ -458,6 +472,7 @@ class MarketMakerBot extends AbstractBot { } } + // NOT USED getQuoteCapital(): number { if (this.quoteUsd) { return parseFloat((this.capitalASideUSD / this.quoteUsd).toFixed(this.quoteDisplayDecimals)); @@ -466,6 +481,7 @@ class MarketMakerBot extends AbstractBot { } } + // returns one tick based on quoteDisplayDecimals getIncrement(): number { let increment = 1 / (Math.pow(10,this.quoteDisplayDecimals)); return increment; diff --git a/services/bots/TakerBot.ts b/services/bots/TakerBot.ts deleted file mode 100644 index e8c9dc9..0000000 --- a/services/bots/TakerBot.ts +++ /dev/null @@ -1,205 +0,0 @@ -import axios from "axios"; -import { getConfig } from "../../config"; -import utils from "../utils"; -import BigNumber from "bignumber.js"; -import AbstractBot from "./AbstractBot"; -import NewOrder from "./classes"; - -class MarketMakerBot extends AbstractBot { - protected marketPrice = new BigNumber(0); - protected baseUsd = 0; - protected quoteUsd = 0; - protected bidSpread: any; - protected askSpread: any; - protected flatAmount: any; - protected timer: any; - protected capitalASideUSD = 300; - - constructor(botId: number, pairStr: string, privateKey: string) { - super(botId, pairStr, privateKey); - // Will try to rebalance the amounts in the Portfolio Contract - this.portfolioRebalanceAtStart = false; - this.config = getConfig(this.tradePairIdentifier); - this.config = this.config.taker; - this.bidSpread = this.config.bidSpread/100; - this.askSpread = this.config.askSpread/100; - this.flatAmount = this.config.flatAmount; - } - - async saveBalancestoDb(balancesRefreshed: boolean): Promise { - this.logger.info(`${this.instanceName} Save Balances somewhere if needed`); - } - - async initialize(): Promise { - const initializing = await super.initialize(); - if (initializing) { - await this.getNewMarketPrice(); - // await this.getBestOrders(); - - this.interval = 5000; - - // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc - //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); - - return true; - } else { - return false; - } - } - - async startOrderUpdater() { - if (this.status) { - // Sleep 30 seconds initially if rebalancing portfolio - if (this.portfolioRebalanceAtStart){ - await utils.sleep(30000); - } - - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - - //Cancel any remaining orders - await this.cancelOrderList([], 100); - - if (this.baseUsd && this.quoteUsd){ - - await this.getBestOrders(); - - // ------------ Begin Order Updater ------------ // - - this.orderUpdater = setTimeout(()=>{ - this.updateOrders(); - }, this.interval/2); - } else { - console.log("MISSING PRICE DATA - baseUsd:",this.baseUsd, " quoteUsd: ",this.quoteUsd, "Wait 10 seconds then try again"); - await utils.sleep(10000); - await this.getNewMarketPrice(); - this.startOrderUpdater(); - } - } else { - this.logger.warn(`${this.instanceName} Bot Status set to false, will not send orders`); - } - } - - async updateOrders() { - if (this.orderUpdater != undefined) { - clearTimeout(this.orderUpdater); - } - if (this.orders.values.length > 0){ - await this.cancelOrderList([],100); - this.timer = 6000; - } - - try { - if (this.status && (this.marketPrice.toNumber() * (1 - this.bidSpread) > this.currentBestAsk || this.marketPrice.toNumber() * (1 + this.askSpread) > this.currentBestBid)){ - this.timer = this.interval; - - // having issues with nonces when avax/usdc and avax/usdt send orders at the same time in the same wallet. This gives priority to avaxusdc. - if (this.tradePairIdentifier == "AVAX/USDt"){ - await utils.sleep(500); - } - await Promise.all([this.getBalances(),this.correctNonce(this.contracts["SubNetProvider"])]); - - if (this.marketPrice.toNumber() * (1 - this.bidSpread) > this.currentBestAsk){ - const bidPrice = new BigNumber(this.marketPrice.toNumber() * (1 - this.bidSpread)); - let quantity = this.getQuantity(bidPrice, 0); - this.addOrder(0,quantity,bidPrice,1,2,0); // immediate or cancel order - } - if (this.marketPrice.toNumber() * (1 + this.askSpread) < this.currentBestBid){ - const askPrice = new BigNumber(this.marketPrice.toNumber() * (1 + this.askSpread)); - let quantity = this.getQuantity(askPrice, 1); - this.addOrder(1,quantity,askPrice,1,2,0); // immediate or cancel order - } - - - } - } catch (error) { - this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); - this.cleanUpAndExit(); - } finally { - //Update orders again after interval - this.orderUpdater = setTimeout(async ()=>{ - if (this.status){ - await Promise.all([this.getNewMarketPrice(),this.getBestOrders(),this.processOpenOrders()]); - this.timer = 2000; - this.updateOrders(); - } - }, this.timer); - } - } - - getQuantity(price: BigNumber, side: number): BigNumber { - if (side == 0){ - if (this.contracts[this.quote].portfolioAvail / price.toNumber() > this.flatAmount){ - return new BigNumber(this.flatAmount); - } else { - return new BigNumber(this.contracts[this.quote].portfolioAvail / price.toNumber()); - } - } else { - if (this.contracts[this.base].portfolioAvail > this.flatAmount){ - return new BigNumber(this.flatAmount); - } else { - return new BigNumber(this.contracts[this.base].portfolioAvail); - } - } - } - - // Update the marketPrice from an outside source - async getNewMarketPrice() { - try { - let response = await axios.get('http://localhost:3000/prices'); - let prices = response.data; - - this.baseUsd = prices[this.base+'-USD']; - this.quoteUsd = prices[this.quote+'-USD']; - - if (this.base == "sAVAX"){ - let totalPooledAvax = await this.savaxContract.totalPooledAvax(); - let totalSupply = await this.savaxContract.totalSupply(); - totalPooledAvax = new BigNumber(totalPooledAvax.toString()); - totalSupply = new BigNumber(totalSupply.toString()); - - this.baseUsd = totalPooledAvax.shiftedBy(-18).div(totalSupply.shiftedBy(-18)).toNumber() * this.quoteUsd * .9992; - } - if (this.baseUsd && this.quoteUsd){ - this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); - console.log("new market Price:",this.marketPrice.toNumber()); - } else { - throw 'trouble getting base or quote prices' - } - } catch (error: any) { - this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); - } - return this.marketPrice; - } - - getPrice(side: number): BigNumber { - return this.marketPrice; - } - - async getAlotPrice(): Promise { - let alotprice = 0.25; - try { - alotprice = 0.25; // FIXME Implement your own price source to get the ALOT price - } catch (error) { - this.logger.error(`${this.instanceName} Error during getAlotPrice`, error); - } - return alotprice; - } - getBaseCapital(): number { - if (this.baseUsd) { - return parseFloat((this.capitalASideUSD / this.baseUsd).toFixed(this.baseDisplayDecimals)); - } else { - return this.initialDepositBase; - } - } - - getQuoteCapital(): number { - if (this.quoteUsd) { - return parseFloat((this.capitalASideUSD / this.quoteUsd).toFixed(this.quoteDisplayDecimals)); - } else { - return this.initialDepositQuote; - } - } - -} - -export default MarketMakerBot; From 7073527954669923cca13e18f3389a0cd2ab992f Mon Sep 17 00:00:00 2001 From: Beastlorion <90943050+Beastlorion@users.noreply.github.com> Date: Fri, 6 Oct 2023 19:48:19 -0500 Subject: [PATCH 109/173] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d164a7e..acafe6f 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ This bot is an alternative to MarketMakerBot. The key difference is instead of r Pros: - Uses far fewer calls, which is good for avoiding rate limitting. (If you're serious about this you'll want to start your own rpc node for unlimitted rpc calls. You can add a custom rpc url to the config file) - The logic is much simpler and easier to understand. + Cons: - Your orders will be off the books for about 8-12 seconds while it is waiting to get confirmation from transactions processing. - I don't actively use this version, so there may still be some bugs that need to be worked out. From 58655b542ad18aa8a05ff69d6f17e3f08755d41f Mon Sep 17 00:00:00 2001 From: Beastlorion <90943050+Beastlorion@users.noreply.github.com> Date: Sat, 7 Oct 2023 12:42:00 -0500 Subject: [PATCH 110/173] Update README.md --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index acafe6f..6dc3abd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Beastlorion's Custom Dexalot Bots +# Beastlorion's Dexalot MarketMaker ## Setup ``` @@ -6,15 +6,14 @@ nvm install 16.15.1 yarn install ``` -You will need funds to trade. - You can get AVAX from fuji faucet and sell your avax against USDC at Dexalot Fuji at https://app.dexalot-test.com if you need more USDC please contact the Dexalot Team. -config parameters are declared in .env.production for production or .env.fuji for testnet -Paste this into your .env.fuji with your private key and address. PLEASE USE A TEST WALLET. +Config parameters are declared in .env.production for production or .env.fuji for testnet. For production, I recommend using a secrets manager for your wallet's private key for enhanced security. Also if you're using a remote server, which you probably should be, you should whitelist the IP that you will be connecting to it from. +Paste this into your .env.fuji with your private key and address. PLEASE USE A TEST WALLET. + ``` { "bot_id" : "100", "bot_type" : "MarketMakerBot", @@ -52,7 +51,7 @@ Examples of other markets: ``` ## To run -- You will need to start a price_feeds instance which serves price data to a local port: (My price feeds: https://github.com/Beastlorion/dexalotBot_price_feeds) +- You will need to start a price_feeds instance which serves price data to a local port: https://github.com/Beastlorion/dexalotBot_price_feeds - You can edit the price calculations there if you'd like. - Once that is running on the same machine, run one of the following: From c1ebe645bf1676981812fef863651ead51ee77d5 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 7 Oct 2023 14:57:52 -0500 Subject: [PATCH 111/173] remove unnecessary code from marketMakerBotOrderLists, update readme, change to depositNative call in abstract class --- README.md | 21 +++-- package.json | 1 + services/bots/AbstractBot.ts | 4 +- services/bots/MarketMakerBotOrderLists.ts | 102 ++-------------------- 4 files changed, 26 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 6dc3abd..7e8e0e0 100644 --- a/README.md +++ b/README.md @@ -53,16 +53,25 @@ Examples of other markets: ## To run - You will need to start a price_feeds instance which serves price data to a local port: https://github.com/Beastlorion/dexalotBot_price_feeds - You can edit the price calculations there if you'd like. -- Once that is running on the same machine, run one of the following: +- Once that is running on the same machine, run one of the following with your pair of choice: Fuji Testnet: ``` -yarn marketMakerBot-fuji --pair="AVAX/USDC" +yarn marketMaker-fuji --pair="AVAX/USDC" ``` +or +``` +yarn marketMakerLists-fuji --pair="AVAX/USDC" +``` + Production: ``` -yarn marketMakerBot-prod --pair="AVAX/USDC" +yarn marketMaker-prod --pair="AVAX/USDC" +``` +or +``` +yarn marketMakerLists-prod --pair="AVAX/USDC" ``` ## Abstract Class Flow @@ -93,16 +102,16 @@ MarketMakerBot extends the AbstractBot implementation. It holds the main logic f - If the conditions for a taker trade are not met, it will begin refreshing the prices and quantities of the orders for the pair taking care to avoid PostOnly trade conflicts. - When it is finished it will set a timer and then begin calling orderUpdater() again. -## MarketMakerBotOrderLists (I don't use this so check it carefully before you use it) +## MarketMakerBotOrderLists (Use this if you do not have your own rpc node) This bot is an alternative to MarketMakerBot. The key difference is instead of replacing individual orders, it will cancel all of the active orders in one call, wait for confirmation, and then place all fresh orders in one call. Pros: - Uses far fewer calls, which is good for avoiding rate limitting. (If you're serious about this you'll want to start your own rpc node for unlimitted rpc calls. You can add a custom rpc url to the config file) - The logic is much simpler and easier to understand. +- Allows for many orders for each pair with lower likelihood of nonce conflicts. You could have 10 or more bids and sells active for each market. Cons: -- Your orders will be off the books for about 8-12 seconds while it is waiting to get confirmation from transactions processing. -- I don't actively use this version, so there may still be some bugs that need to be worked out. +- Your orders will be off the books for about 6-8 seconds each time they need to be cancelled and replaced. ## DISCLAIMER diff --git a/package.json b/package.json index 9a9f97a..b0c8837 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "author": "Cengiz Dincoglu", "scripts": { "marketMaker-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMaker --NODE_ENV_SETTINGS=fuji", + "marketMakerLists-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMakerLists --NODE_ENV_SETTINGS=fuji", "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMaker --NODE_ENV_SETTINGS=production", "marketMakerLists-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMakerLists --NODE_ENV_SETTINGS=production", "taker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=taker --NODE_ENV_SETTINGS=production" diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 28813bd..17aa55f 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -206,7 +206,7 @@ abstract class AbstractBot { await this.getTokenDetails(); this.contracts["MainnetProvider"] = { provider: this.getProvider(this.getEnvironment("mainnet").chain_instance), nonce: 0 }; - if (getConfig("NODE_ENV_SETTINGS") == "production"){ + if (getConfig("NODE_ENV_SETTINGS") == "production" && getConfig("rpc_url")){ this.contracts["SubNetProvider"] = { provider: this.getProvider(getConfig("rpc_url"), this.ratelimit_token), nonce: 0 @@ -1808,7 +1808,7 @@ abstract class AbstractBot { if (alot.subnetBal < 10) { deposit_amount = (10 - alot.subnetBal).toFixed(5); if (alot.portfolioAvail > 10) { - await this.withdrawNative(this.contracts["Portfoliosub"].deployedContract, deposit_amount, alot.tokenDetails.evmdecimals); + await this.depositNative(this.contracts["Portfoliosub"].deployedContract, deposit_amount, alot.tokenDetails.evmdecimals); } else { await this.depositToken(alot.deployedContract, alot.inByte32, alot.tokenDetails.evmdecimals, deposit_amount); } diff --git a/services/bots/MarketMakerBotOrderLists.ts b/services/bots/MarketMakerBotOrderLists.ts index bbe79ee..e678ccb 100644 --- a/services/bots/MarketMakerBotOrderLists.ts +++ b/services/bots/MarketMakerBotOrderLists.ts @@ -45,13 +45,9 @@ class MarketMakerBot extends AbstractBot { const initializing = await super.initialize(); if (initializing) { await this.getNewMarketPrice(); - // await this.getBestOrders(); this.interval = 15000; //Min 10 seconds - // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc - //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); - return true; } else { return false; @@ -110,22 +106,22 @@ class MarketMakerBot extends AbstractBot { this.lastUpdate = Date.now(); this.timer = this.interval; console.log("000000000000000 COUNTER:",this.orderUpdaterCounter); - - // having issues with nonces when avax/usdc and avax/usdt send orders at the same time. This gives priority to avaxusdc - if (this.tradePairIdentifier == "AVAX/USDt"){ - await utils.sleep(500); - } + // Refresh orders, balances, and get new best bid and ask prices await Promise.all([this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders(),this.getBalances(),this.getBestOrders()]); + + // Cancel all orders, when finished, trigger the new order placement. const promise = Promise.resolve(this.cancelOrderList([], 100)); + if (this.baseUsd && this.quoteUsd){ - // ------------ Create and Send Initial Order List ------------ // + // ------------ Create new Order List ------------ // let levels : number[][] = []; for (let i = 1; i <= this.orderLevels; i++){ levels.push([0,i]); levels.push([1,i]); } + // Gets all order records let bids: any[] = []; let asks: any[] = []; let duplicates: any[] = []; @@ -160,6 +156,7 @@ class MarketMakerBot extends AbstractBot { } }); + // This code finds how much funds are currently on open orders which you're cancelling so that it can determine how much is available for new orders let onBids = 0; let onAsks = 0; for (let i = 0; i < bids.length;i++){ @@ -172,6 +169,7 @@ class MarketMakerBot extends AbstractBot { let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * 0.999; onAsks+= amountOnOrder; } + // finally, we correct the nonce one last time and then create and send the new orders promise.then(async()=>{ await this.correctNonce(this.contracts["SubNetProvider"]) await this.placeInitialOrders(levels, parseFloat(this.contracts[this.quote].portfolioAvail) + onBids, parseFloat(this.contracts[this.base].portfolioAvail) + onAsks); @@ -249,90 +247,6 @@ class MarketMakerBot extends AbstractBot { this.lastUpdate = Date.now(); } - async replaceBids(bidsSorted: any, startingBidPrice: number){ - console.log("REPLACE BIDS: ",bidsSorted.length); - let quoteAvail = parseFloat(this.contracts[this.quote].portfolioAvail); - for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0, price: new BigNumber(0)}; - for (let j = 0; j < bidsSorted.length; j++){ - if (bidsSorted[j].level == i+1){ - order = bidsSorted[j]; - } - } - - if (order.id){ - let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.999; - let availableFunds = quoteAvail + amountOnOrder; - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); - let amountToPlace = bidQty; - if (availableFunds/bidPrice.toNumber() < amountToPlace.toNumber()){ - amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); - } - if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - console.log("REPLACE ORDER:",amountToPlace.toNumber(),bidQty.toNumber(), i+1); - quoteAvail -= bidQty.toNumber() * bidPrice.toNumber() - amountOnOrder - this.cancelReplaceOrder(order,bidPrice,amountToPlace); - } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), quoteAvail, availableFunds, amountOnOrder, amountToPlace.toNumber()); - this.cancelOrder(order); - } - } else { - //set aside funds to create new orders - let amount = this.getLevelQty(i+1) * startingBidPrice; - if (amount < quoteAvail){ - quoteAvail -= amount; - this.placeInitialOrders([[0,i+1]],amount,); - } else { - this.placeInitialOrders([[0,i+1]],quoteAvail,); - quoteAvail = 0; - } - } - } - } - - async replaceAsks (asksSorted: any, startingAskPrice: number){ - console.log("REPLACE ASKS: ",asksSorted.length); - let baseAvail = parseFloat(this.contracts[this.base].portfolioAvail); - - for (let i = 0; i < this.orderLevels; i ++){ - let order = {id:null, status:null, quantity:new BigNumber(0),quantityfilled:new BigNumber(0), level:0}; - for (let j = 0; j < asksSorted.length; j++){ - if (asksSorted[j].level == i+1){ - order = asksSorted[j]; - } - } - if (order.id){ - let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .999; - let availableFunds = baseAvail + amountOnOrder; - - let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); - let amountToPlace = askQty; - if (availableFunds < askQty.toNumber()){ - amountToPlace = new BigNumber(availableFunds * .999); - } - baseAvail -= askQty.toNumber() - amountOnOrder; - if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - console.log("REPLACE ORDER:",askPrice.toNumber(),amountToPlace.toNumber(), i+1); - this.cancelReplaceOrder(order,askPrice,amountToPlace); - } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", amountToPlace.toNumber(), availableFunds); - this.cancelOrder(order); - } - } else { - let amount = this.getLevelQty(i+1) * 1.01; - if (amount < baseAvail){ - this.placeInitialOrders([[1,i+1]],undefined,amount); - baseAvail -= amount; - } else { - this.placeInitialOrders([[1,i+1]],undefined,baseAvail); - baseAvail = 0; - } - } - } - } - // Takes in price, side, level, and availableFunds. Returns amount to place. // If there are enough availableFunds, it will return the intended amount according to configs, otherwise it will return as much as it can, otherwise it will return 0 getQty(price: BigNumber, side: number, level: number, availableFunds: number): number { From 17d493485fbc6b3ad4a060437527f6b9d0e4a3c8 Mon Sep 17 00:00:00 2001 From: Beastlorion <90943050+Beastlorion@users.noreply.github.com> Date: Mon, 9 Oct 2023 09:32:29 -0500 Subject: [PATCH 112/173] Update README.md --- README.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7e8e0e0..af8d67a 100644 --- a/README.md +++ b/README.md @@ -55,25 +55,29 @@ Examples of other markets: - You can edit the price calculations there if you'd like. - Once that is running on the same machine, run one of the following with your pair of choice: +MarketMakerLists (RECOMMENDED for beginners) Fuji Testnet: ``` -yarn marketMaker-fuji --pair="AVAX/USDC" -``` -or -``` yarn marketMakerLists-fuji --pair="AVAX/USDC" ``` - Production: ``` -yarn marketMaker-prod --pair="AVAX/USDC" +yarn marketMakerLists-prod --pair="AVAX/USDC" +``` + +Alternatively, if you have a custom rpc node, use this version to keep your orders active at all times: +Fuji Testnet: +``` +yarn marketMakerLists-fuji --pair="AVAX/USDC" ``` -or + +Production: ``` yarn marketMakerLists-prod --pair="AVAX/USDC" ``` + ## Abstract Class Flow AbstractBot performs various functions: - Get the mainnet/subnet environments, pairs listed, token details from the RESTAPI @@ -102,16 +106,17 @@ MarketMakerBot extends the AbstractBot implementation. It holds the main logic f - If the conditions for a taker trade are not met, it will begin refreshing the prices and quantities of the orders for the pair taking care to avoid PostOnly trade conflicts. - When it is finished it will set a timer and then begin calling orderUpdater() again. -## MarketMakerBotOrderLists (Use this if you do not have your own rpc node) +## MarketMakerBotOrderLists (Recommended if not using your own rpc node) This bot is an alternative to MarketMakerBot. The key difference is instead of replacing individual orders, it will cancel all of the active orders in one call, wait for confirmation, and then place all fresh orders in one call. Pros: - Uses far fewer calls, which is good for avoiding rate limitting. (If you're serious about this you'll want to start your own rpc node for unlimitted rpc calls. You can add a custom rpc url to the config file) - The logic is much simpler and easier to understand. -- Allows for many orders for each pair with lower likelihood of nonce conflicts. You could have 10 or more bids and sells active for each market. +- Allows for many orders for each pair with lower likelihood of errors. You could have 10 or more bids and sells active for each market. Cons: - Your orders will be off the books for about 6-8 seconds each time they need to be cancelled and replaced. +- Currently does not have taker orders enabled. ## DISCLAIMER From 362b9d930db42dce582c3ef7fdc9ebbc682ffc31 Mon Sep 17 00:00:00 2001 From: Beastlorion <90943050+Beastlorion@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:57:21 -0500 Subject: [PATCH 113/173] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index af8d67a..2ce2bd8 100644 --- a/README.md +++ b/README.md @@ -69,12 +69,12 @@ yarn marketMakerLists-prod --pair="AVAX/USDC" Alternatively, if you have a custom rpc node, use this version to keep your orders active at all times: Fuji Testnet: ``` -yarn marketMakerLists-fuji --pair="AVAX/USDC" +yarn marketMaker-fuji --pair="AVAX/USDC" ``` Production: ``` -yarn marketMakerLists-prod --pair="AVAX/USDC" +yarn marketMaker-prod --pair="AVAX/USDC" ``` From dacdad3bf3a721baf1b4be70b71758f3223dd0b9 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Fri, 27 Oct 2023 10:51:08 -0500 Subject: [PATCH 114/173] fix taker bid amount --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 3a14e65..eca7c4d 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -193,7 +193,7 @@ class MarketMakerBot extends AbstractBot { await this.cancelOrderList([]); let bidAmount: any = 0; - if ((this.contracts[this.quote].portfolioTot / takerBidPrice) > this.maxTradeAmnt){ + if (this.contracts[this.quote].portfolioTot > this.maxTradeAmnt){ bidAmount = new BigNumber((this.maxTradeAmnt / takerBidPrice) * .99); } else { bidAmount = new BigNumber((this.contracts[this.quote].portfolioTot / takerBidPrice) * .99); From caf686a4b3a691062d4b14fd356f4bfc50682660 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 29 Oct 2023 13:36:09 -0500 Subject: [PATCH 115/173] add defensiveSkew to config + getBidSpread() + getAskSpread() --- services/bots/AbstractBot.ts | 1 + services/bots/MarketMakerBot.ts | 51 ++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 17aa55f..0239867 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -212,6 +212,7 @@ abstract class AbstractBot { nonce: 0 }; } else { + console.log("Use default subnetProvider") this.contracts["SubNetProvider"] = { provider: this.getProvider(this.getEnvironment("subnet").chain_instance, this.ratelimit_token), nonce: 0 diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index eca7c4d..6d373f9 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -24,6 +24,8 @@ class MarketMakerBot extends AbstractBot { protected timer: any; protected lastBaseUsd: any; protected lastUpdate: any; + protected defensiveSkew: any; + protected defensiveSkewMax: any; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -39,6 +41,7 @@ class MarketMakerBot extends AbstractBot { this.flatAmount = this.config.flatAmount; this.takerSpread = this.config.takerSpread/100; this.takerEnabled = this.config.takerEnabled; + this.defensiveSkew = this.config.defensiveSkew/100; this.lastUpdate = 0; } @@ -52,7 +55,7 @@ class MarketMakerBot extends AbstractBot { await this.getNewMarketPrice(); // await this.getBestOrders(); - this.interval = 15000; //Min 10 seconds + this.interval = 8000; //Min 8 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -124,9 +127,15 @@ class MarketMakerBot extends AbstractBot { // updates balances, gets best bids and asks, and corrects the nonce await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); - let startingBidPriceBG = this.marketPrice.multipliedBy(1-this.bidSpread).dp(this.quoteDisplayDecimals, BigNumber.ROUND_DOWN); + + let bidSpread = this.getBidSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot)); + let askSpread = this.getAskSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot)); + console.log("bidSpread: ", bidSpread) + console.log("askSpread: ", askSpread) + + let startingBidPriceBG = this.marketPrice.multipliedBy(1-bidSpread).dp(this.quoteDisplayDecimals, BigNumber.ROUND_DOWN); let startingBidPrice = startingBidPriceBG.toNumber(); - let startingAskPriceBG = this.marketPrice.multipliedBy(1+this.askSpread).dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP); + let startingAskPriceBG = this.marketPrice.multipliedBy(1+askSpread).dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP); let startingAskPrice = startingAskPriceBG.toNumber(); // if the bid and ask are the same price, increase the ask by one tick @@ -257,9 +266,14 @@ class MarketMakerBot extends AbstractBot { // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ console.log("PLACING INITAL ORDERS: ",levels); + let bidSpread = this.getBidSpread(availableBase*this.marketPrice.toNumber()/availableQuote); + let askSpread = this.getAskSpread(availableBase*this.marketPrice.toNumber()/availableQuote); + console.log("bidSpread: ", bidSpread) + console.log("askSpread: ", askSpread) + + let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-bidSpread)).toFixed(this.quoteDisplayDecimals)); + let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+askSpread)).toFixed(this.quoteDisplayDecimals)); - let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); - let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); initialBidPrice = this.currentBestAsk && this.currentBestAsk <= initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; initialAskPrice = this.currentBestBid && this.currentBestBid >= initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; @@ -267,7 +281,7 @@ class MarketMakerBot extends AbstractBot { // --------------- SET BIDS --------------- // for (let x = 0; x < levels.length; x++){ if (levels[x][0] == 0){ - let bidPrice = new BigNumber((initialBidPrice * (1-this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); + let bidPrice = new BigNumber((initialBidPrice * (1-this.getOrderLevelSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); let bidQty = new BigNumber(this.getQty(bidPrice,0,levels[x][1],availableQuote)); if (bidQty.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ availableQuote -= bidQty.toNumber() * bidPrice.toNumber(); @@ -278,7 +292,7 @@ class MarketMakerBot extends AbstractBot { } } else { //--------------- SET ASKS --------------- // - let askPrice = new BigNumber((initialAskPrice * (1+this.getSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); + let askPrice = new BigNumber((initialAskPrice * (1+this.getOrderLevelSpread(levels[x][1]-1))).toFixed(this.quoteDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,levels[x][1],availableBase)); if (askQty.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ availableBase -= askQty.toNumber(); @@ -316,7 +330,7 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ - let bidPrice = new BigNumber((startingBidPrice * (1-this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); + let bidPrice = new BigNumber((startingBidPrice * (1-this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.999; let availableFunds = quoteAvail + amountOnOrder; let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); @@ -362,7 +376,7 @@ class MarketMakerBot extends AbstractBot { let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .999; let availableFunds = baseAvail + amountOnOrder; - let askPrice = new BigNumber((startingAskPrice * (1+this.getSpread(i))).toFixed(this.quoteDisplayDecimals)); + let askPrice = new BigNumber((startingAskPrice * (1+this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); let amountToPlace = askQty; if (availableFunds < askQty.toNumber()){ @@ -418,10 +432,27 @@ class MarketMakerBot extends AbstractBot { } // returns % away from market price to place order - getSpread(level:number):number{ + getOrderLevelSpread(level:number):number{ return (level*parseFloat(this.orderLevelSpread)) } + getBidSpread(multiple:number):number{ + let defensiveSkew = 0; + if (multiple >= 2 && this.defensiveSkew){ + defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + } + return this.bidSpread + defensiveSkew; + } + + getAskSpread(multiple:number):number{ + let defensiveSkew = 0; + if (1/multiple > 2 && this.defensiveSkew){ + multiple = 1/multiple; + defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + } + return this.askSpread + defensiveSkew; + } + // Update the marketPrice from price feed bot async getNewMarketPrice() { try { From 57159bc6eff1c58670ecb8e8445ff204a42c2e35 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 29 Oct 2023 14:06:03 -0500 Subject: [PATCH 116/173] add slip for volatile markets and add defensiveSkew config to readme --- README.md | 3 ++- services/bots/MarketMakerBot.ts | 26 +++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7e8e0e0..c8df80b 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ Paste this into your .env.fuji with your private key and address. PLEASE USE A T "orderLevels" : "2", "orderLevelSpread" : "0.30", "orderLevelQty" : "0.5", - "refreshOrderTolerance" : "0.05" + "refreshOrderTolerance" : "0.05", + "defensiveSkew" : "0.5" } } ``` diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 6d373f9..085aa05 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -127,9 +127,9 @@ class MarketMakerBot extends AbstractBot { // updates balances, gets best bids and asks, and corrects the nonce await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); - - let bidSpread = this.getBidSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot)); - let askSpread = this.getAskSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot)); + let change = Math.abs(this.marketPrice.toNumber()-this.lastMarketPrice.toNumber())/this.marketPrice.toNumber(); + let bidSpread = this.getBidSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot),change); + let askSpread = this.getAskSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot),change); console.log("bidSpread: ", bidSpread) console.log("askSpread: ", askSpread) @@ -266,8 +266,8 @@ class MarketMakerBot extends AbstractBot { // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ console.log("PLACING INITAL ORDERS: ",levels); - let bidSpread = this.getBidSpread(availableBase*this.marketPrice.toNumber()/availableQuote); - let askSpread = this.getAskSpread(availableBase*this.marketPrice.toNumber()/availableQuote); + let bidSpread = this.getBidSpread(availableBase*this.marketPrice.toNumber()/availableQuote,0); + let askSpread = this.getAskSpread(availableBase*this.marketPrice.toNumber()/availableQuote,0); console.log("bidSpread: ", bidSpread) console.log("askSpread: ", askSpread) @@ -436,21 +436,29 @@ class MarketMakerBot extends AbstractBot { return (level*parseFloat(this.orderLevelSpread)) } - getBidSpread(multiple:number):number{ + getBidSpread(multiple:number,change:number):number{ + let slip = 0; + if (change > this.refreshOrderTolerance * 2){ + slip = change - this.refreshOrderTolerance; + } let defensiveSkew = 0; if (multiple >= 2 && this.defensiveSkew){ defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 } - return this.bidSpread + defensiveSkew; + return this.bidSpread + defensiveSkew + slip; } - getAskSpread(multiple:number):number{ + getAskSpread(multiple:number,change:number):number{ + let slip = 0; + if (change > this.refreshOrderTolerance * 2){ + slip = change - this.refreshOrderTolerance; + } let defensiveSkew = 0; if (1/multiple > 2 && this.defensiveSkew){ multiple = 1/multiple; defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 } - return this.askSpread + defensiveSkew; + return this.askSpread + defensiveSkew + slip; } // Update the marketPrice from price feed bot From 0ec3f9dfff2d1f7487573eed4d6b969c6012c9e6 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 29 Oct 2023 15:00:11 -0500 Subject: [PATCH 117/173] lower leeway in orderamounts by 10x --- services/bots/MarketMakerBot.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 085aa05..0a2ab51 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -331,12 +331,12 @@ class MarketMakerBot extends AbstractBot { if (order.id){ let bidPrice = new BigNumber((startingBidPrice * (1-this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); - let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.999; + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.9999; let availableFunds = quoteAvail + amountOnOrder; let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); let amountToPlace = bidQty; if (availableFunds/bidPrice.toNumber() < amountToPlace.toNumber()){ - amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); + amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.9999); } if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ console.log("REPLACE ORDER:",bidPrice.toNumber(),bidQty.toNumber(), i+1); @@ -373,14 +373,14 @@ class MarketMakerBot extends AbstractBot { } } if (order.id){ - let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .999; + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .9999; let availableFunds = baseAvail + amountOnOrder; let askPrice = new BigNumber((startingAskPrice * (1+this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); let amountToPlace = askQty; if (availableFunds < askQty.toNumber()){ - amountToPlace = new BigNumber(availableFunds * .999); + amountToPlace = new BigNumber(availableFunds * .9999); } baseAvail -= askQty.toNumber() - amountOnOrder; if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ @@ -411,14 +411,14 @@ class MarketMakerBot extends AbstractBot { if (this.getLevelQty(level) < availableFunds/price.toNumber()){ return this.getLevelQty(level); } else if (availableFunds > this.minTradeAmnt * 2){ - return availableFunds/price.toNumber() * .999; + return availableFunds/price.toNumber() * .9999; } else { return 0;} } else if (side === 1) { console.log("AVAILABLE FUNDS ASK: ",availableFunds, "AMOUNT: ",this.getLevelQty(level)) if (this.getLevelQty(level) < availableFunds){ return this.getLevelQty(level); } else if (availableFunds * price.toNumber() > this.minTradeAmnt * 2){ - return availableFunds * .999; + return availableFunds * .9999; } else {return 0;} } else { return 0; // function declaration requires I return a number From eb5b42aa1fc677f5638ca182153c524c678b8966 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 29 Oct 2023 16:31:21 -0500 Subject: [PATCH 118/173] refactoring bid ask spreads, fixing related bugs --- services/bots/MarketMakerBot.ts | 44 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 0a2ab51..ca976ab 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -23,9 +23,10 @@ class MarketMakerBot extends AbstractBot { protected takerEnabled: any; protected timer: any; protected lastBaseUsd: any; - protected lastUpdate: any; + protected lastUpdate = 0; protected defensiveSkew: any; protected defensiveSkewMax: any; + protected lastChange = 0; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -42,7 +43,6 @@ class MarketMakerBot extends AbstractBot { this.takerSpread = this.config.takerSpread/100; this.takerEnabled = this.config.takerEnabled; this.defensiveSkew = this.config.defensiveSkew/100; - this.lastUpdate = 0; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -127,15 +127,11 @@ class MarketMakerBot extends AbstractBot { // updates balances, gets best bids and asks, and corrects the nonce await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); - let change = Math.abs(this.marketPrice.toNumber()-this.lastMarketPrice.toNumber())/this.marketPrice.toNumber(); - let bidSpread = this.getBidSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot),change); - let askSpread = this.getAskSpread(parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot),change); - console.log("bidSpread: ", bidSpread) - console.log("askSpread: ", askSpread) + this.lastChange = Math.abs(this.marketPrice.toNumber()-this.lastMarketPrice.toNumber())/this.marketPrice.toNumber(); - let startingBidPriceBG = this.marketPrice.multipliedBy(1-bidSpread).dp(this.quoteDisplayDecimals, BigNumber.ROUND_DOWN); + let startingBidPriceBG = this.marketPrice.multipliedBy(1-this.getBidSpread()).dp(this.quoteDisplayDecimals, BigNumber.ROUND_DOWN); let startingBidPrice = startingBidPriceBG.toNumber(); - let startingAskPriceBG = this.marketPrice.multipliedBy(1+askSpread).dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP); + let startingAskPriceBG = this.marketPrice.multipliedBy(1+this.getAskSpread()).dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP); let startingAskPrice = startingAskPriceBG.toNumber(); // if the bid and ask are the same price, increase the ask by one tick @@ -266,13 +262,9 @@ class MarketMakerBot extends AbstractBot { // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ console.log("PLACING INITAL ORDERS: ",levels); - let bidSpread = this.getBidSpread(availableBase*this.marketPrice.toNumber()/availableQuote,0); - let askSpread = this.getAskSpread(availableBase*this.marketPrice.toNumber()/availableQuote,0); - console.log("bidSpread: ", bidSpread) - console.log("askSpread: ", askSpread) - let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-bidSpread)).toFixed(this.quoteDisplayDecimals)); - let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+askSpread)).toFixed(this.quoteDisplayDecimals)); + let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.getBidSpread())).toFixed(this.quoteDisplayDecimals)); + let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.getAskSpread())).toFixed(this.quoteDisplayDecimals)); initialBidPrice = this.currentBestAsk && this.currentBestAsk <= initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; initialAskPrice = this.currentBestBid && this.currentBestBid >= initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; @@ -436,29 +428,35 @@ class MarketMakerBot extends AbstractBot { return (level*parseFloat(this.orderLevelSpread)) } - getBidSpread(multiple:number,change:number):number{ + getBidSpread():number{ let slip = 0; - if (change > this.refreshOrderTolerance * 2){ - slip = change - this.refreshOrderTolerance; + if (this.lastChange > this.refreshOrderTolerance * 2){ + slip = this.lastChange - this.refreshOrderTolerance; } let defensiveSkew = 0; + let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); if (multiple >= 2 && this.defensiveSkew){ defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 } - return this.bidSpread + defensiveSkew + slip; + let bidSpread = this.bidSpread + defensiveSkew + slip; + console.log("Bid Spread:",bidSpread); + return bidSpread; } - getAskSpread(multiple:number,change:number):number{ + getAskSpread():number{ let slip = 0; - if (change > this.refreshOrderTolerance * 2){ - slip = change - this.refreshOrderTolerance; + if (this.lastChange > this.refreshOrderTolerance * 2){ + slip = this.lastChange - this.refreshOrderTolerance; } let defensiveSkew = 0; + let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); if (1/multiple > 2 && this.defensiveSkew){ multiple = 1/multiple; defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 } - return this.askSpread + defensiveSkew + slip; + let askSpread = this.askSpread + defensiveSkew + slip; + console.log("Bid Spread:",askSpread); + return askSpread; } // Update the marketPrice from price feed bot From 72a4957a835edd81f008b9596ef82517f03f3b6b Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sun, 29 Oct 2023 18:30:31 -0500 Subject: [PATCH 119/173] give back some leeway to amount to replace --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index ca976ab..1646483 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -328,7 +328,7 @@ class MarketMakerBot extends AbstractBot { let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); let amountToPlace = bidQty; if (availableFunds/bidPrice.toNumber() < amountToPlace.toNumber()){ - amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.9999); + amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); } if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ console.log("REPLACE ORDER:",bidPrice.toNumber(),bidQty.toNumber(), i+1); @@ -372,7 +372,7 @@ class MarketMakerBot extends AbstractBot { let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); let amountToPlace = askQty; if (availableFunds < askQty.toNumber()){ - amountToPlace = new BigNumber(availableFunds * .9999); + amountToPlace = new BigNumber(availableFunds * .999); } baseAvail -= askQty.toNumber() - amountOnOrder; if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ From df7ee7590088978abcb3d6ddb316ab7b87844b2f Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 30 Oct 2023 09:47:13 -0500 Subject: [PATCH 120/173] add fix for taker buy amounts --- services/bots/MarketMakerBot.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 1646483..9ad4906 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -194,11 +194,11 @@ class MarketMakerBot extends AbstractBot { // if takerEnabled is true and best orders are outside of the takerspread, create an immediate or cancel order at the taker price. Otherwise replace orders as usual. - if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk && (parseFloat(this.contracts[this.quote].portfolioTot) / takerBidPrice) > this.minTradeAmnt) { //taker bid + if (this.takerEnabled && currentBestAsk && takerBidPrice > currentBestAsk && parseFloat(this.contracts[this.quote].portfolioTot) > this.minTradeAmnt) { //taker bid await this.cancelOrderList([]); let bidAmount: any = 0; - if (this.contracts[this.quote].portfolioTot > this.maxTradeAmnt){ + if (parseFloat(this.contracts[this.quote].portfolioTot) > this.maxTradeAmnt){ bidAmount = new BigNumber((this.maxTradeAmnt / takerBidPrice) * .99); } else { bidAmount = new BigNumber((this.contracts[this.quote].portfolioTot / takerBidPrice) * .99); @@ -208,7 +208,7 @@ class MarketMakerBot extends AbstractBot { await this.addOrder(0,bidAmount,bidPrice,1,2,0); this.lastMarketPrice = new BigNumber(0); - } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && parseFloat(this.contracts[this.base].portfolioTot) > this.minTradeAmnt){ // taker ask + } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && parseFloat(this.contracts[this.base].portfolioTot) * takerBidPrice > this.minTradeAmnt){ // taker ask await this.cancelOrderList([]); let askAmount: any = 0; From d339bcf753493f0299e1ebbfad1830211aba158e Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Mon, 30 Oct 2023 10:29:34 -0500 Subject: [PATCH 121/173] use addorderList function. also add warning if addorder fails without a reason --- services/bots/AbstractBot.ts | 11 +++++------ services/bots/MarketMakerBot.ts | 13 +++---------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 0239867..f5bb47c 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -742,12 +742,11 @@ abstract class AbstractBot { }, 2000) } } else { - // this.logger.error( - // `${this.instanceName} addOrder error: ${side === 0 ? "BUY" : "SELL"} ${quantity ? quantity.toString() : "undefined"} @ ${ - // price ? price.toString() : "undefined" - // }`, - // error - // ); + this.logger.warn( + `${this.instanceName} addOrder error: ${side === 0 ? "BUY" : "SELL"} ${quantity ? quantity.toString() : "undefined"} @ ${ + price ? price.toString() : "undefined" + } Revert Reason ${reason}` + ); } } } diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 9ad4906..3bec48e 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -297,15 +297,8 @@ class MarketMakerBot extends AbstractBot { } // // --------------- EXECUTE ORDERS --------------- // - if (newOrderList.length == 0){ - } else if (newOrderList.length == 1){ - if (this.status){ - this.addOrder(newOrderList[0].side,newOrderList[0].quantity,newOrderList[0].price,1,3,newOrderList[0].level); - } - } else { - if (this.status){ - this.addLimitOrderList(newOrderList); - } + if (this.status && newOrderList.length > 0){ + this.addLimitOrderList(newOrderList); } } @@ -455,7 +448,7 @@ class MarketMakerBot extends AbstractBot { defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 } let askSpread = this.askSpread + defensiveSkew + slip; - console.log("Bid Spread:",askSpread); + console.log("Ask Spread:",askSpread); return askSpread; } From 0ef33bdc06e7ff3bd5bfb0aff2f572434cfc66c2 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 31 Oct 2023 10:55:04 -0500 Subject: [PATCH 122/173] add retrigger in case orders were not placed at ideal prices --- services/bots/MarketMakerBot.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 3bec48e..de86eed 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -27,6 +27,7 @@ class MarketMakerBot extends AbstractBot { protected defensiveSkew: any; protected defensiveSkewMax: any; protected lastChange = 0; + protected retrigger = false; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -112,10 +113,11 @@ class MarketMakerBot extends AbstractBot { } try { - if (this.status && ((Date.now() - this.lastUpdate)/1000 > 600 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ + if (this.status && (this.retrigger || (Date.now() - this.lastUpdate)/1000 > 600 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ this.orderUpdaterCounter ++; this.lastUpdate = Date.now(); this.timer = this.interval; + this.retrigger = false; console.log("000000000000000 COUNTER:",this.orderUpdaterCounter); // Uncomment the following when running both avax markets on the same wallet at the same time to avoid nonce errors because avax/usdc and avax/usdt tend to send orders at the same time. This gives priority to avaxusdc @@ -206,7 +208,8 @@ class MarketMakerBot extends AbstractBot { let bidPrice = new BigNumber(takerBidPrice); console.log("TAKER BUY,",bidAmount,"at: ",bidPrice); await this.addOrder(0,bidAmount,bidPrice,1,2,0); - this.lastMarketPrice = new BigNumber(0); + this.lastMarketPrice = this.marketPrice; + this.retrigger = true; } else if (this.takerEnabled && currentBestBid && takerAskPrice < currentBestBid && parseFloat(this.contracts[this.base].portfolioTot) * takerBidPrice > this.minTradeAmnt){ // taker ask await this.cancelOrderList([]); @@ -220,7 +223,8 @@ class MarketMakerBot extends AbstractBot { let askPrice = new BigNumber(takerAskPrice); console.log("TAKER SELL,",askAmount,"at: ",askPrice); await this.addOrder(1,askAmount,askPrice,1,2,0); - this.lastMarketPrice = new BigNumber(0); + this.lastMarketPrice = this.marketPrice; + this.retrigger = true; } else if (currentBestAsk && startingBidPrice >= currentBestAsk){ // adjust prices if startingBidPrice is higher than the bestAsk. Then replace all orders. @@ -229,6 +233,7 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; + this.retrigger = true; } else if (currentBestBid && startingAskPrice <= currentBestBid){ // adjust prices if startingAskPrice is lower than the bestBid. Then replace all orders. let startingAskPriceBG = new BigNumber(currentBestBid + this.getIncrement()) @@ -236,6 +241,7 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; + this.retrigger = true; } else { // replace all orders await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); From 0ca87d2c31493274b81f43cb604c5e68bec83103 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 31 Oct 2023 11:38:04 -0500 Subject: [PATCH 123/173] add retrigger conditions to skip if best prices haven't changed --- services/bots/MarketMakerBot.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index de86eed..f720b87 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -28,6 +28,8 @@ class MarketMakerBot extends AbstractBot { protected defensiveSkewMax: any; protected lastChange = 0; protected retrigger = false; + protected lastBestBid = 0; + protected lastBestAsk = 0; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -117,7 +119,6 @@ class MarketMakerBot extends AbstractBot { this.orderUpdaterCounter ++; this.lastUpdate = Date.now(); this.timer = this.interval; - this.retrigger = false; console.log("000000000000000 COUNTER:",this.orderUpdaterCounter); // Uncomment the following when running both avax markets on the same wallet at the same time to avoid nonce errors because avax/usdc and avax/usdt tend to send orders at the same time. This gives priority to avaxusdc @@ -147,6 +148,13 @@ class MarketMakerBot extends AbstractBot { const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; + if (this.retrigger && currentBestAsk == this.lastBestAsk && currentBestBid == this.lastBestBid){ // if trying to get better order placement, but best order prices haven't changed, exit and try again next round. + return; + } else { + this.lastBestAsk = currentBestAsk; + this.lastBestBid = currentBestBid; + } + let bids: any[] = []; let asks: any[] = []; let duplicates: any[] = []; @@ -246,6 +254,7 @@ class MarketMakerBot extends AbstractBot { } else { // replace all orders await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; + this.retrigger = false; } } From 4e31002430d4189abaf21973b1f9a8f6bf74d3c5 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 31 Oct 2023 15:17:57 -0500 Subject: [PATCH 124/173] fix bug in skip retrigger --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index f720b87..a59986b 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -148,7 +148,7 @@ class MarketMakerBot extends AbstractBot { const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; - if (this.retrigger && currentBestAsk == this.lastBestAsk && currentBestBid == this.lastBestBid){ // if trying to get better order placement, but best order prices haven't changed, exit and try again next round. + if (this.retrigger && currentBestAsk == this.lastBestAsk && currentBestBid == this.lastBestBid && startingBidPrice >= currentBestBid && startingAskPrice <= currentBestAsk){ // if trying to get better order placement, but best order prices haven't changed, exit and try again next round. return; } else { this.lastBestAsk = currentBestAsk; From 1415f334d4e449e419512be812a322e5da808e24 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 31 Oct 2023 15:51:28 -0500 Subject: [PATCH 125/173] remove extra retrigger conditions --- services/bots/MarketMakerBot.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index a59986b..289268a 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -148,13 +148,6 @@ class MarketMakerBot extends AbstractBot { const currentBestAsk = this.currentBestAsk ? this.currentBestAsk : undefined; const currentBestBid = this.currentBestBid ? this.currentBestBid : undefined; - if (this.retrigger && currentBestAsk == this.lastBestAsk && currentBestBid == this.lastBestBid && startingBidPrice >= currentBestBid && startingAskPrice <= currentBestAsk){ // if trying to get better order placement, but best order prices haven't changed, exit and try again next round. - return; - } else { - this.lastBestAsk = currentBestAsk; - this.lastBestBid = currentBestBid; - } - let bids: any[] = []; let asks: any[] = []; let duplicates: any[] = []; From 895259ff44fa96158c3f3cb4b711ac45a3377e00 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 31 Oct 2023 16:22:17 -0500 Subject: [PATCH 126/173] only retrigger when has enough funds to bother, implies within price range --- services/bots/MarketMakerBot.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 289268a..8ac78f4 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -234,15 +234,18 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; - this.retrigger = true; - + if (parseFloat(this.contracts[this.quote].portfolioTot) > this.minTradeAmnt * 2){ + this.retrigger = true; + } } else if (currentBestBid && startingAskPrice <= currentBestBid){ // adjust prices if startingAskPrice is lower than the bestBid. Then replace all orders. let startingAskPriceBG = new BigNumber(currentBestBid + this.getIncrement()) startingAskPrice = startingAskPriceBG.dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP).toNumber(); await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; - this.retrigger = true; + if (parseFloat(this.contracts[this.base].portfolioTot) * takerBidPrice > this.minTradeAmnt * 2){ + this.retrigger = true; + } } else { // replace all orders await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); From b026a0a887a87a827981f79614493c5edf0b366d Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 31 Oct 2023 16:37:08 -0500 Subject: [PATCH 127/173] move retrigger to abstract class, set to true if failed to cancelreplace --- services/bots/AbstractBot.ts | 5 ++++- services/bots/MarketMakerBot.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index f5bb47c..1d261e4 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -68,6 +68,7 @@ abstract class AbstractBot { protected currentBestBid: any; protected currentBestAsk: any; protected counter: any; + protected retrigger = false; constructor(botId: number, pairStr: string, privateKey: string, ratelimit_token?: string) { this.logger = getLogger("Bot"); @@ -1375,7 +1376,7 @@ abstract class AbstractBot { return; } if (tries > 1){ - this.cancelOrder(order); + this.retrigger = true; return } @@ -1457,6 +1458,8 @@ abstract class AbstractBot { if (reason) { if (reason == "T-OAEX-01"){ this.removeOrderFromMap(order); + } else if (reason == "T-T2PO-01"){ + this.retrigger = true; } else { this.logger.warn( `${this.instanceName} Order Cancel/Replace error ${order.side === 0 ? "BUY" : "SELL"} ::: ${quantity.toFixed( diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 8ac78f4..78f7356 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -27,9 +27,9 @@ class MarketMakerBot extends AbstractBot { protected defensiveSkew: any; protected defensiveSkewMax: any; protected lastChange = 0; - protected retrigger = false; protected lastBestBid = 0; protected lastBestAsk = 0; + public retrigger = false; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); From 3ab4e5989ed20ba2c887e5e82f5947874f6dee6a Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 1 Nov 2023 09:58:39 -0500 Subject: [PATCH 128/173] add slip config --- services/bots/MarketMakerBot.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 78f7356..91bed14 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -25,11 +25,10 @@ class MarketMakerBot extends AbstractBot { protected lastBaseUsd: any; protected lastUpdate = 0; protected defensiveSkew: any; - protected defensiveSkewMax: any; + protected slip: any; protected lastChange = 0; protected lastBestBid = 0; protected lastBestAsk = 0; - public retrigger = false; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -46,6 +45,7 @@ class MarketMakerBot extends AbstractBot { this.takerSpread = this.config.takerSpread/100; this.takerEnabled = this.config.takerEnabled; this.defensiveSkew = this.config.defensiveSkew/100; + this.slip = this.config.slip; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -434,7 +434,7 @@ class MarketMakerBot extends AbstractBot { getBidSpread():number{ let slip = 0; - if (this.lastChange > this.refreshOrderTolerance * 2){ + if (this.lastChange > this.refreshOrderTolerance * 2 && this.slip){ slip = this.lastChange - this.refreshOrderTolerance; } let defensiveSkew = 0; @@ -449,7 +449,7 @@ class MarketMakerBot extends AbstractBot { getAskSpread():number{ let slip = 0; - if (this.lastChange > this.refreshOrderTolerance * 2){ + if (this.lastChange > this.refreshOrderTolerance * 2 && this.slip){ slip = this.lastChange - this.refreshOrderTolerance; } let defensiveSkew = 0; From 55979640840920358e18ae09147343cad270c1d1 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 1 Nov 2023 12:52:05 -0500 Subject: [PATCH 129/173] add useretrigger config --- services/bots/MarketMakerBot.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 91bed14..6d7dd92 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -29,6 +29,7 @@ class MarketMakerBot extends AbstractBot { protected lastChange = 0; protected lastBestBid = 0; protected lastBestAsk = 0; + protected useRetrigger = false; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -46,6 +47,7 @@ class MarketMakerBot extends AbstractBot { this.takerEnabled = this.config.takerEnabled; this.defensiveSkew = this.config.defensiveSkew/100; this.slip = this.config.slip; + this.useRetrigger = this.config.useRetrigger } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -234,7 +236,7 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; - if (parseFloat(this.contracts[this.quote].portfolioTot) > this.minTradeAmnt * 2){ + if (parseFloat(this.contracts[this.quote].portfolioTot) > this.minTradeAmnt * 2 && this.useRetrigger){ this.retrigger = true; } } else if (currentBestBid && startingAskPrice <= currentBestBid){ // adjust prices if startingAskPrice is lower than the bestBid. Then replace all orders. @@ -243,7 +245,7 @@ class MarketMakerBot extends AbstractBot { await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); this.lastMarketPrice = this.marketPrice; - if (parseFloat(this.contracts[this.base].portfolioTot) * takerBidPrice > this.minTradeAmnt * 2){ + if (parseFloat(this.contracts[this.base].portfolioTot) * takerBidPrice > this.minTradeAmnt * 2 && this.useRetrigger){ this.retrigger = true; } From c9c0960fd24485c247c616020055bff4e03fbbec Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Fri, 10 Nov 2023 10:47:11 -0600 Subject: [PATCH 130/173] fix bug with retrigger continuing to fire when set to false --- README.md | 4 +++- services/bots/MarketMakerBot.ts | 6 ++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bffbee0..1347283 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,9 @@ Paste this into your .env.fuji with your private key and address. PLEASE USE A T "orderLevelSpread" : "0.30", "orderLevelQty" : "0.5", "refreshOrderTolerance" : "0.05", - "defensiveSkew" : "0.5" + "defensiveSkew" : "0.5", + "slip" : false, + "useRetrigger" : false } } ``` diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 6d7dd92..a8f7293 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -27,8 +27,6 @@ class MarketMakerBot extends AbstractBot { protected defensiveSkew: any; protected slip: any; protected lastChange = 0; - protected lastBestBid = 0; - protected lastBestAsk = 0; protected useRetrigger = false; constructor(botId: number, pairStr: string, privateKey: string) { @@ -238,7 +236,7 @@ class MarketMakerBot extends AbstractBot { this.lastMarketPrice = this.marketPrice; if (parseFloat(this.contracts[this.quote].portfolioTot) > this.minTradeAmnt * 2 && this.useRetrigger){ this.retrigger = true; - } + } else {this.retrigger = false;} } else if (currentBestBid && startingAskPrice <= currentBestBid){ // adjust prices if startingAskPrice is lower than the bestBid. Then replace all orders. let startingAskPriceBG = new BigNumber(currentBestBid + this.getIncrement()) startingAskPrice = startingAskPriceBG.dp(this.quoteDisplayDecimals,BigNumber.ROUND_UP).toNumber(); @@ -247,7 +245,7 @@ class MarketMakerBot extends AbstractBot { this.lastMarketPrice = this.marketPrice; if (parseFloat(this.contracts[this.base].portfolioTot) * takerBidPrice > this.minTradeAmnt * 2 && this.useRetrigger){ this.retrigger = true; - } + } else {this.retrigger = false;} } else { // replace all orders await Promise.all([this.replaceBids(bidsSorted, startingBidPrice),this.replaceAsks(asksSorted, startingAskPrice)]); From 85e616b235e4a1ff00de3db0c40144b3022c345d Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Tue, 14 Nov 2023 16:59:48 -0600 Subject: [PATCH 131/173] slip = lastchange/2 --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index a8f7293..f1e62ef 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -435,7 +435,7 @@ class MarketMakerBot extends AbstractBot { getBidSpread():number{ let slip = 0; if (this.lastChange > this.refreshOrderTolerance * 2 && this.slip){ - slip = this.lastChange - this.refreshOrderTolerance; + slip = this.lastChange/2; } let defensiveSkew = 0; let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); From 0b2568997f64e2d6e034b0a24cef5036ba1fe951 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 15 Nov 2023 17:12:37 -0600 Subject: [PATCH 132/173] implement independentOrders and hardcode addOrderLimitList gas --- services/bots/AbstractBot.ts | 2 +- services/bots/MarketMakerBot.ts | 112 ++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 35 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 1d261e4..4227a83 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -484,7 +484,7 @@ abstract class AbstractBot { try { - const gasest = await this.getAddOrderListGasEstimate(clientOrderIds, prices, quantities, sides, type2s); + const gasest = BigNumberEthers.from(750000 * clientOrderIds.length);//await this.getAddOrderListGasEstimate(clientOrderIds, prices, quantities, sides, type2s); // failing to calculate accurately during busy times this.logger.warn(`${this.instanceName} Gas Est ${gasest.toString()}`); const tx = await this.tradePair.addLimitOrderList( diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index f1e62ef..b8c4955 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -28,6 +28,8 @@ class MarketMakerBot extends AbstractBot { protected slip: any; protected lastChange = 0; protected useRetrigger = false; + protected useIndependentLevels: boolean = false; + protected independentLevels: any; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -46,6 +48,9 @@ class MarketMakerBot extends AbstractBot { this.defensiveSkew = this.config.defensiveSkew/100; this.slip = this.config.slip; this.useRetrigger = this.config.useRetrigger + this.useIndependentLevels = this.config.useIndependentLevels + this.independentLevels = this.config.independentLevels; + console.log('this.independentLevels',this.independentLevels) } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -58,7 +63,7 @@ class MarketMakerBot extends AbstractBot { await this.getNewMarketPrice(); // await this.getBestOrders(); - this.interval = 8000; //Min 8 seconds + this.interval = 10000; //Min 8 seconds // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -326,21 +331,24 @@ class MarketMakerBot extends AbstractBot { } if (order.id){ - let bidPrice = new BigNumber((startingBidPrice * (1-this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); - let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.9999; - let availableFunds = quoteAvail + amountOnOrder; - let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); - let amountToPlace = bidQty; - if (availableFunds/bidPrice.toNumber() < amountToPlace.toNumber()){ - amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); - } - if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ - console.log("REPLACE ORDER:",bidPrice.toNumber(),bidQty.toNumber(), i+1); - quoteAvail -= bidQty.toNumber() * bidPrice.toNumber() - amountOnOrder - this.cancelReplaceOrder(order,bidPrice,amountToPlace); - } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), quoteAvail, availableFunds, amountOnOrder, amountToPlace.toNumber()); - this.cancelOrder(order); + if (this.refreshLevel(i+1,true)){ + let bidPrice = new BigNumber((startingBidPrice * (1-this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber())*order.price.toNumber() * 0.9999; + let availableFunds = quoteAvail + amountOnOrder; + let bidQty = new BigNumber(this.getQty(bidPrice,0,i+1,availableFunds)); + let amountToPlace = bidQty; + if (availableFunds/bidPrice.toNumber() < amountToPlace.toNumber()){ + amountToPlace = new BigNumber((availableFunds/bidPrice.toNumber())*.999); + } + if (amountToPlace.toNumber() * bidPrice.toNumber() > this.minTradeAmnt){ + console.log("REPLACE ORDER:",bidPrice.toNumber(),bidQty.toNumber(), i+1); + quoteAvail -= bidQty.toNumber() * bidPrice.toNumber() - amountOnOrder + this.cancelReplaceOrder(order,bidPrice,amountToPlace); + this.setLevelRefreshPrice(i+1,true); + } else { + console.log("NOT ENOUGH FUNDS TO REPLACE", bidQty.toNumber() * bidPrice.toNumber(), quoteAvail, availableFunds, amountOnOrder, amountToPlace.toNumber()); + this.cancelOrder(order); + } } } else { //set aside funds to create new orders @@ -369,22 +377,25 @@ class MarketMakerBot extends AbstractBot { } } if (order.id){ - let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .9999; - let availableFunds = baseAvail + amountOnOrder; - - let askPrice = new BigNumber((startingAskPrice * (1+this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); - let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); - let amountToPlace = askQty; - if (availableFunds < askQty.toNumber()){ - amountToPlace = new BigNumber(availableFunds * .999); - } - baseAvail -= askQty.toNumber() - amountOnOrder; - if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ - console.log("REPLACE ORDER:",askPrice.toNumber(),amountToPlace.toNumber(), i+1); - this.cancelReplaceOrder(order,askPrice,amountToPlace); - } else { - console.log("NOT ENOUGH FUNDS TO REPLACE", amountToPlace.toNumber(), availableFunds); - this.cancelOrder(order); + if (this.refreshLevel(i+1,false)){ + let amountOnOrder = (order.quantity.toNumber()-order.quantityfilled.toNumber()) * .9999; + let availableFunds = baseAvail + amountOnOrder; + + let askPrice = new BigNumber((startingAskPrice * (1+this.getOrderLevelSpread(i))).toFixed(this.quoteDisplayDecimals)); + let askQty = new BigNumber(this.getQty(askPrice,1,i+1,availableFunds)); + let amountToPlace = askQty; + if (availableFunds < askQty.toNumber()){ + amountToPlace = new BigNumber(availableFunds * .999); + } + baseAvail -= askQty.toNumber() - amountOnOrder; + if (amountToPlace.toNumber() * askPrice.toNumber() > this.minTradeAmnt){ + console.log("REPLACE ORDER:",askPrice.toNumber(),amountToPlace.toNumber(), i+1); + this.cancelReplaceOrder(order,askPrice,amountToPlace); + this.setLevelRefreshPrice(i+1,false); + } else { + console.log("NOT ENOUGH FUNDS TO REPLACE", amountToPlace.toNumber(), availableFunds); + this.cancelOrder(order); + } } } else { let amount = this.getLevelQty(i+1) * 1.01; @@ -424,12 +435,20 @@ class MarketMakerBot extends AbstractBot { // returns amount to place for given order level in base asset getLevelQty(level:number):number{ - return parseFloat(this.flatAmount) + (parseFloat(this.orderLevelQty) * (level-1)); + if (level != 1 && this.useIndependentLevels && this.independentLevels[(level).toString()].customQty){ + return this.independentLevels[(level).toString()].customQty; + } else { + return parseFloat(this.flatAmount) + (parseFloat(this.orderLevelQty) * (level-1)); + } } // returns % away from market price to place order getOrderLevelSpread(level:number):number{ - return (level*parseFloat(this.orderLevelSpread)) + if (level != 0 && this.useIndependentLevels && this.independentLevels[(level+1).toString()].customSpread){ + return parseFloat(this.independentLevels[(level+1).toString()].customSpread); + } else { + return (level*parseFloat(this.orderLevelSpread)) + } } getBidSpread():number{ @@ -489,6 +508,31 @@ class MarketMakerBot extends AbstractBot { return this.marketPrice; } + refreshLevel(level:number,isBid : boolean): boolean { + if (level == 1){ + return true; + } + let lastUpdateBid = this.independentLevels[level.toString()].lastUpdateBid; + let lastUpdateAsk = this.independentLevels[level.toString()].lastUpdateAsk; + console.log("level:",level,"isBid",isBid,"lastUpdateBid",lastUpdateBid,"lastUpdateAsk",lastUpdateAsk); + if (isBid){ + return !lastUpdateBid || Math.abs(lastUpdateBid - this.marketPrice.toNumber()) / lastUpdateBid > this.independentLevels[level.toString()].tolerance/100; + } else { + return !lastUpdateAsk || Math.abs(lastUpdateAsk - this.marketPrice.toNumber()) / lastUpdateAsk > this.independentLevels[level.toString()].tolerance/100; + } + } + + setLevelRefreshPrice(level:number,isBid:boolean){ + if (level == 1){ + return; + } + if (isBid){ + this.independentLevels[level.toString()].lastUpdateBid = this.marketPrice.toNumber(); + } else { + this.independentLevels[level.toString()].lastUpdateAsk = this.marketPrice.toNumber(); + } + } + // not used getPrice(side: number): BigNumber { return this.marketPrice; From 8799a37ebefb06eb7032804c9fa01ea38728f0b8 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 15 Nov 2023 17:30:13 -0600 Subject: [PATCH 133/173] C:/Program Files/Git/100 for independent spreads --- services/bots/MarketMakerBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index b8c4955..76f4d10 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -445,7 +445,7 @@ class MarketMakerBot extends AbstractBot { // returns % away from market price to place order getOrderLevelSpread(level:number):number{ if (level != 0 && this.useIndependentLevels && this.independentLevels[(level+1).toString()].customSpread){ - return parseFloat(this.independentLevels[(level+1).toString()].customSpread); + return parseFloat(this.independentLevels[(level+1).toString()].customSpread)/100; } else { return (level*parseFloat(this.orderLevelSpread)) } From a7ed71159060399425e6a8134b795ff5c099f647 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Thu, 16 Nov 2023 10:15:17 -0600 Subject: [PATCH 134/173] check for useIndependentLevels --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 76f4d10..c2c0ff8 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -509,7 +509,7 @@ class MarketMakerBot extends AbstractBot { } refreshLevel(level:number,isBid : boolean): boolean { - if (level == 1){ + if (level == 1 || !this.useIndependentLevels){ return true; } let lastUpdateBid = this.independentLevels[level.toString()].lastUpdateBid; @@ -523,7 +523,7 @@ class MarketMakerBot extends AbstractBot { } setLevelRefreshPrice(level:number,isBid:boolean){ - if (level == 1){ + if (level == 1 || !this.useIndependentLevels){ return; } if (isBid){ From 9e19085c7d323c4adc75321968e5933334358d8f Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Thu, 16 Nov 2023 12:06:45 -0600 Subject: [PATCH 135/173] add slip and defensiveSkew for marketMakerLists --- services/bots/MarketMakerBotOrderLists.ts | 42 +++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBotOrderLists.ts b/services/bots/MarketMakerBotOrderLists.ts index e678ccb..a455cb6 100644 --- a/services/bots/MarketMakerBotOrderLists.ts +++ b/services/bots/MarketMakerBotOrderLists.ts @@ -22,6 +22,9 @@ class MarketMakerBot extends AbstractBot { protected timer: any; protected lastBaseUsd: any; protected lastUpdate: any; + protected lastChange: number; + protected defensiveSkew: number; + protected slip: boolean; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -35,6 +38,9 @@ class MarketMakerBot extends AbstractBot { this.orderLevelQty = this.config.orderLevelQty; this.refreshOrderTolerance = this.config.refreshOrderTolerance/100; this.flatAmount = this.config.flatAmount; + this.defensiveSkew = this.config.defensiveSkew/100; + this.slip = this.config.slip; + this.lastChange = 0; } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -109,6 +115,7 @@ class MarketMakerBot extends AbstractBot { // Refresh orders, balances, and get new best bid and ask prices await Promise.all([this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders(),this.getBalances(),this.getBestOrders()]); + this.lastChange = Math.abs(this.marketPrice.toNumber()-this.lastMarketPrice.toNumber())/this.marketPrice.toNumber(); // Cancel all orders, when finished, trigger the new order placement. const promise = Promise.resolve(this.cancelOrderList([], 100)); @@ -197,8 +204,8 @@ class MarketMakerBot extends AbstractBot { // For each subarray passed in, it creates a new order and adds it to newOrderList. At the end it calls addLimitOrderList with the newOrderList async placeInitialOrders(levels: number[][], availableQuote: number = this.contracts[this.quote].portfolioAvail, availableBase: number = this.contracts[this.base].portfolioAvail){ - let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.bidSpread)).toFixed(this.quoteDisplayDecimals)); - let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.askSpread)).toFixed(this.quoteDisplayDecimals)); + let initialBidPrice = parseFloat((this.marketPrice.toNumber() * (1-this.getBidSpread())).toFixed(this.quoteDisplayDecimals)); + let initialAskPrice = parseFloat((this.marketPrice.toNumber() * (1+this.getAskSpread())).toFixed(this.quoteDisplayDecimals)); initialBidPrice = this.currentBestAsk && this.currentBestAsk <= initialBidPrice ? this.currentBestAsk - this.getIncrement() : initialBidPrice; initialAskPrice = this.currentBestBid && this.currentBestBid >= initialAskPrice ? this.currentBestBid + this.getIncrement() : initialAskPrice; @@ -273,6 +280,37 @@ class MarketMakerBot extends AbstractBot { return parseFloat(this.flatAmount) + (parseFloat(this.orderLevelQty) * (level-1)); } + getBidSpread():number{ + let slip = 0; + if (this.lastChange > this.refreshOrderTolerance * 2 && this.slip){ + slip = this.lastChange/2; + } + let defensiveSkew = 0; + let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); + if (multiple >= 2 && this.defensiveSkew){ + defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + } + let bidSpread = this.bidSpread + defensiveSkew + slip; + console.log("Bid Spread:",bidSpread); + return bidSpread; + } + + getAskSpread():number{ + let slip = 0; + if (this.lastChange > this.refreshOrderTolerance * 2 && this.slip){ + slip = this.lastChange - this.refreshOrderTolerance; + } + let defensiveSkew = 0; + let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); + if (1/multiple > 2 && this.defensiveSkew){ + multiple = 1/multiple; + defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + } + let askSpread = this.askSpread + defensiveSkew + slip; + console.log("Ask Spread:",askSpread); + return askSpread; + } + getSpread(level:number):number{ return (level*parseFloat(this.orderLevelSpread)) } From de064c812ef9a7ac346b64bcda0a068df83c5a8a Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Thu, 16 Nov 2023 13:21:48 -0600 Subject: [PATCH 136/173] remove cleanUpAndExit call when failing to place order list --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 4227a83..c84de3b 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -426,7 +426,7 @@ abstract class AbstractBot { async addLimitOrderList(newOrders: NewOrder[], tries: number = 0) { if(tries > 1){ - this.cleanUpAndExit(); + console.log("failed to addLimitOrderList"); return } From 57f4292e05e509ec5b7dbf928875773eef8dc890 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 18 Nov 2023 09:06:27 -0600 Subject: [PATCH 137/173] add variable orderRefreshTime --- services/bots/MarketMakerBotOrderLists.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBotOrderLists.ts b/services/bots/MarketMakerBotOrderLists.ts index a455cb6..590f032 100644 --- a/services/bots/MarketMakerBotOrderLists.ts +++ b/services/bots/MarketMakerBotOrderLists.ts @@ -18,6 +18,7 @@ class MarketMakerBot extends AbstractBot { protected orderLevelSpread: any; protected orderLevelQty: any; protected refreshOrderTolerance: any; + protected refreshOrderTime: any; protected flatAmount: any; protected timer: any; protected lastBaseUsd: any; @@ -37,6 +38,10 @@ class MarketMakerBot extends AbstractBot { this.orderLevelSpread = this.config.orderLevelSpread/100; this.orderLevelQty = this.config.orderLevelQty; this.refreshOrderTolerance = this.config.refreshOrderTolerance/100; + this.refreshOrderTime = this.config.refreshOrderTime; + if (typeof this.refreshOrderTime == "undefined"){ + this.refreshOrderTime = 900; // set to 15 minutes if it hasn't been declared + } this.flatAmount = this.config.flatAmount; this.defensiveSkew = this.config.defensiveSkew/100; this.slip = this.config.slip; @@ -107,7 +112,7 @@ class MarketMakerBot extends AbstractBot { try { console.log(Date.now(), this.lastUpdate) - if (this.status && ((Date.now() - this.lastUpdate)/1000 > 20 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ + if (this.status && (((this.refreshOrderTime && Date.now() - this.lastUpdate)/1000 > this.refreshOrderTime) || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ this.orderUpdaterCounter ++; this.lastUpdate = Date.now(); this.timer = this.interval; From 0fa402c0d3248b3a94aae538813dfd0b239f7938 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 18 Nov 2023 09:09:58 -0600 Subject: [PATCH 138/173] update readme environment variables --- README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1347283..2d4e7ae 100644 --- a/README.md +++ b/README.md @@ -33,10 +33,24 @@ Paste this into your .env.fuji with your private key and address. PLEASE USE A T "orderLevelSpread" : "0.30", "orderLevelQty" : "0.5", "refreshOrderTolerance" : "0.05", - "defensiveSkew" : "0.5", + "refreshOrderTime" : "0", + "defensiveSkew" : "0", "slip" : false, - "useRetrigger" : false - } + "useIndependentLevels" : false, + "independentLevels": + { + "2":{ + "customQty" : "2", + "customSpread": "0.4", + "tolerance": "0.3" + }, + "3":{ + "customQty" : "4", + "customSpread": "1", + "tolerance": "0.75" + } + } + }, } ``` From 7ac9f737451396804b7e1dbc77113a2851223954 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 08:15:45 -0600 Subject: [PATCH 139/173] add analytics bot --- package.json | 3 +- services/bots/AbstractBot.ts | 10 ++++ services/bots/Analytics.ts | 97 ++++++++++++++++++++++++++++++++++++ services/bots/BotFactory.ts | 3 +- 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 services/bots/Analytics.ts diff --git a/package.json b/package.json index b0c8837..6e9fc8f 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "marketMakerLists-fuji": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMakerLists --NODE_ENV_SETTINGS=fuji", "marketMaker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMaker --NODE_ENV_SETTINGS=production", "marketMakerLists-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=marketMakerLists --NODE_ENV_SETTINGS=production", - "taker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=taker --NODE_ENV_SETTINGS=production" + "taker-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=taker --NODE_ENV_SETTINGS=production", + "analytics-prod": "tsc && node prepare && node ./dist-js/services/bots/botLauncher.js --bot_type=analytics --NODE_ENV_SETTINGS=production" }, "dependencies": { "@ethersproject/experimental": "5.7.0", diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index c84de3b..066683a 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1491,6 +1491,16 @@ abstract class AbstractBot { } } + async getFilledOrders(startDate:any = new Date(Date.now()-86400000).toISOString(),endDate:any = new Date(Date.now()).toISOString()) { + try { + const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate, this.axiosConfig)) + .data; + return orders.rows; + } catch (error: any) { + this.logger.error(`${this.instanceName} ${error}`); + } + } + async processOpenOrders() { //this.logger.info(`${this.instanceName} Recovering open orders:`); const orders = await this.getOpenOrders(); diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts new file mode 100644 index 0000000..0459122 --- /dev/null +++ b/services/bots/Analytics.ts @@ -0,0 +1,97 @@ +import axios from "axios"; +import { getConfig } from "../../config"; +import utils from "../utils"; +import BigNumber from "bignumber.js"; +import AbstractBot from "./AbstractBot"; +import NewOrder from "./classes"; + +class Analytics extends AbstractBot { + + constructor(botId: number, pairStr: string, privateKey: string) { + super(botId, pairStr, privateKey); + this.portfolioRebalanceAtStart = false; + this.config = getConfig(this.tradePairIdentifier); + } + + async saveBalancestoDb(balancesRefreshed: boolean): Promise { + this.logger.info(`${this.instanceName} Save Balances somewhere if needed`); + } + + async initialize(): Promise { + const initializing = await super.initialize(); + if (initializing) { + const filledOrders = await this.getFilledOrders(new Date(Date.now()-(86400000*30)).toISOString()); + this.runAnalytics(filledOrders); + process.exit(1); + + return true; + } else { + return false; + } + } + + runAnalytics (filledOrders: any) { + let totalCost = 0; + let totalSold = 0; + let qtyOutstanding = 0; + let totalFees = 0; + let takerBuys = 0; + let takerSells = 0; + filledOrders.forEach((e:any) => { + if (e.side == 0){ + qtyOutstanding += parseFloat(e.quantityfilled); + let fee = e.totalfee * e.price; + totalFees += fee; + totalCost += e.quantityfilled * e.price; + if (e.type2 == 2){ + takerBuys += e.quantityFilled * e.price; + } + } else if (e.side == 1){ + qtyOutstanding-=parseFloat(e.quantityfilled); + totalFees += e.totalfee; + totalSold += e.quantityfilled * e.price + if (e.type2 == 2){ + takerSells += e.quantityFilled * e.price; + } + } + }); + let realizedGains = totalCost - totalSold; + console.log("REALIZED GAINS:",realizedGains,"QTY OUTSTANDING:",qtyOutstanding, "TAKER BUYS:", takerBuys, "TAKER SELLS:",takerSells); + } + + async startOrderUpdater() { + } + + // Update the marketPrice from an outside source + async getNewMarketPrice() { + return new BigNumber(0); + } + + getPrice(side: number): BigNumber { + return new BigNumber(0); + } + + async getAlotPrice(): Promise { + let alotprice = 0.25; + try { + alotprice = 0.25; // FIXME Implement your own price source to get the ALOT price + } catch (error) { + this.logger.error(`${this.instanceName} Error during getAlotPrice`, error); + } + return alotprice; + } + + getBaseCapital(): number { + return 0; + } + + getQuoteCapital(): number { + return 0; + } + + getIncrement(): number { + return 0; + } +} + +export default Analytics; diff --git a/services/bots/BotFactory.ts b/services/bots/BotFactory.ts index c1c0d76..99a7414 100644 --- a/services/bots/BotFactory.ts +++ b/services/bots/BotFactory.ts @@ -1,6 +1,7 @@ import MarketMakerBot from "./MarketMakerBot"; import MarketMakerBotOrderLists from "./MarketMakerBotOrderLists"; -const Bot:any = {marketMaker: MarketMakerBot, marketMakerLists: MarketMakerBotOrderLists}; +import Analytics from "./Analytics"; +const Bot:any = {marketMaker: MarketMakerBot, marketMakerLists: MarketMakerBotOrderLists, analytics: Analytics}; module.exports = { createBot(type:any, attributes:any) { From 8478442fe8a3c44bfc449c8861b96d2e4291d121 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 08:59:21 -0600 Subject: [PATCH 140/173] adding additional analytics fields and calculations --- services/bots/Analytics.ts | 61 +++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts index 0459122..cea96db 100644 --- a/services/bots/Analytics.ts +++ b/services/bots/Analytics.ts @@ -35,28 +35,53 @@ class Analytics extends AbstractBot { let totalSold = 0; let qtyOutstanding = 0; let totalFees = 0; - let takerBuys = 0; - let takerSells = 0; + let makerBuysQty = 0; + let makerBuysAmt = 0; + let makerSellsQty = 0; + let makerSellsAmt = 0; + let takerBuysQty = 0; + let takerBuysAmt = 0; + let takerSellsQty = 0; + let takerSellsAmt = 0; + let totalVolumeQuote = 0; + let totalVolumeBase = 0; + let avgBuyPrice = 0; + let avgSellPrice = 0; filledOrders.forEach((e:any) => { - if (e.side == 0){ - qtyOutstanding += parseFloat(e.quantityfilled); - let fee = e.totalfee * e.price; - totalFees += fee; - totalCost += e.quantityfilled * e.price; - if (e.type2 == 2){ - takerBuys += e.quantityFilled * e.price; - } - } else if (e.side == 1){ - qtyOutstanding-=parseFloat(e.quantityfilled); - totalFees += e.totalfee; - totalSold += e.quantityfilled * e.price - if (e.type2 == 2){ - takerSells += e.quantityFilled * e.price; + if (e.type2 == 2 || e.type2 == 3){ + if (e.side == 0){ + qtyOutstanding += parseFloat(e.quantityfilled); + let fee = e.totalfee * e.price; + totalFees += fee; + totalCost += e.quantityfilled * e.price; + if (e.type2 == 2){ + takerBuysAmt += e.quantityfilled * e.price; + takerBuysQty += e.quantityfilled; + } else { + makerBuysAmt += e.quantityfilled * e.price; + makerBuysQty += e.quantityfilled; + } + } else if (e.side == 1){ + qtyOutstanding-=parseFloat(e.quantityfilled); + totalFees += e.totalfee; + totalSold += e.quantityfilled * e.price + if (e.type2 == 2){ + takerSellsAmt += e.quantityfilled * e.price; + takerSellsQty += e.quantityfilled; + console.log(e); + } else { + makerSellsAmt += e.quantityfilled * e.price; + takerSellsQty += e.quantityfilled; + } } } + totalVolumeBase += e.quantityFilled; + totalVolumeQuote += e.quantityFilled * e.price; }); - let realizedGains = totalCost - totalSold; - console.log("REALIZED GAINS:",realizedGains,"QTY OUTSTANDING:",qtyOutstanding, "TAKER BUYS:", takerBuys, "TAKER SELLS:",takerSells); + avgBuyPrice = (takerBuysAmt+makerBuysAmt)/(takerBuysQty+makerBuysQty); + avgSellPrice = (takerSellsAmt+makerSellsAmt)/(takerSellsQty+makerSellsQty); + + console.log("AVG BUY:",avgBuyPrice, "AVG SELL:", avgSellPrice,"QTY OUTSTANDING:",qtyOutstanding,"MAKER BUYS AMT:", makerBuysAmt, "MAKER SELLS AMT:",makerSellsAmt, "TAKER BUYS AMT:", takerBuysAmt, "TAKER SELLS AMT:",takerSellsAmt, "TotalVolumeBase:",totalVolumeBase,"TotalVolumeQuote:",totalVolumeQuote, "TOTAL FEES:", totalFees); } async startOrderUpdater() { From e5d8b9e49feb2a5ca933f4c60b6e28fd6f423cfa Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 09:04:10 -0600 Subject: [PATCH 141/173] more analytics --- services/bots/Analytics.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts index cea96db..ea1cd84 100644 --- a/services/bots/Analytics.ts +++ b/services/bots/Analytics.ts @@ -56,22 +56,21 @@ class Analytics extends AbstractBot { totalCost += e.quantityfilled * e.price; if (e.type2 == 2){ takerBuysAmt += e.quantityfilled * e.price; - takerBuysQty += e.quantityfilled; + takerBuysQty += parseFloat(e.quantityfilled); } else { makerBuysAmt += e.quantityfilled * e.price; - makerBuysQty += e.quantityfilled; + makerBuysQty += parseFloat(e.quantityfilled); } } else if (e.side == 1){ qtyOutstanding-=parseFloat(e.quantityfilled); - totalFees += e.totalfee; + totalFees += parseFloat(e.totalfee); totalSold += e.quantityfilled * e.price if (e.type2 == 2){ takerSellsAmt += e.quantityfilled * e.price; - takerSellsQty += e.quantityfilled; - console.log(e); + takerSellsQty += parseFloat(e.quantityfilled); } else { makerSellsAmt += e.quantityfilled * e.price; - takerSellsQty += e.quantityfilled; + takerSellsQty += parseFloat(e.quantityfilled); } } } From b94af750df23e7f5db5a4828a566f060184a0c42 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 09:21:53 -0600 Subject: [PATCH 142/173] add custom dates --- services/bots/AbstractBot.ts | 3 +++ services/bots/Analytics.ts | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 066683a..eee2692 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1492,6 +1492,9 @@ abstract class AbstractBot { } async getFilledOrders(startDate:any = new Date(Date.now()-86400000).toISOString(),endDate:any = new Date(Date.now()).toISOString()) { + + console.log("START DATE:",startDate); + console.log("END DATE:",endDate); try { const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate, this.axiosConfig)) .data; diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts index ea1cd84..298dc05 100644 --- a/services/bots/Analytics.ts +++ b/services/bots/Analytics.ts @@ -6,11 +6,15 @@ import AbstractBot from "./AbstractBot"; import NewOrder from "./classes"; class Analytics extends AbstractBot { + protected startDate: number = 0; + protected endDate: number = 0; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); this.portfolioRebalanceAtStart = false; this.config = getConfig(this.tradePairIdentifier); + this.startDate = parseInt(getConfig("startDate")?getConfig("startDate"):"0"); + this.endDate = parseInt(getConfig("endDate")?getConfig("endDate"):"0"); } async saveBalancestoDb(balancesRefreshed: boolean): Promise { @@ -20,7 +24,15 @@ class Analytics extends AbstractBot { async initialize(): Promise { const initializing = await super.initialize(); if (initializing) { - const filledOrders = await this.getFilledOrders(new Date(Date.now()-(86400000*30)).toISOString()); + let startDate = Date.now()-(86400000*30); + let endDate = Date.now(); + if (this.startDate){ + startDate = this.startDate; + } + if (this.endDate){ + endDate = this.endDate; + } + const filledOrders = await this.getFilledOrders(new Date(startDate).toISOString(),new Date(endDate).toISOString()); this.runAnalytics(filledOrders); process.exit(1); From 37a73fe2b1a26c2304029f426f640c010d118ff6 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 10:02:53 -0600 Subject: [PATCH 143/173] concat order rows and use pages --- services/bots/AbstractBot.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index eee2692..b89fa6b 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1496,9 +1496,21 @@ abstract class AbstractBot { console.log("START DATE:",startDate); console.log("END DATE:",endDate); try { - const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate, this.axiosConfig)) - .data; - return orders.rows; + let keepRunning = true; + let i = 1; + let rows: any = []; + while(keepRunning = true){ + const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage=50"+"&pageno="+i, this.axiosConfig)) + .data; + if (orders.rows.length > 0 && i <= 5){ + console.log(orders.rows); + rows.concat(orders.rows); + i ++; + } else { + keepRunning = false; + return rows; + } + } } catch (error: any) { this.logger.error(`${this.instanceName} ${error}`); } From 8535a507297eda42a3a794b712d92e79202d7fb6 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 10:09:36 -0600 Subject: [PATCH 144/173] fix concat --- services/bots/AbstractBot.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index b89fa6b..2f885d5 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1503,8 +1503,7 @@ abstract class AbstractBot { const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage=50"+"&pageno="+i, this.axiosConfig)) .data; if (orders.rows.length > 0 && i <= 5){ - console.log(orders.rows); - rows.concat(orders.rows); + rows = rows.concat(orders.rows); i ++; } else { keepRunning = false; From 3b7ba44156ba031a0f90266cffdbae96b4061552 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 10:11:42 -0600 Subject: [PATCH 145/173] remove page limit but add wait --- services/bots/AbstractBot.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 2f885d5..ccc6fb5 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1502,8 +1502,9 @@ abstract class AbstractBot { while(keepRunning = true){ const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage=50"+"&pageno="+i, this.axiosConfig)) .data; - if (orders.rows.length > 0 && i <= 5){ + if (orders.rows.length > 0){ rows = rows.concat(orders.rows); + utils.sleep(50); i ++; } else { keepRunning = false; From f6f95c31c65e87245abf3004cb9713f83814e53a Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 10:37:41 -0600 Subject: [PATCH 146/173] change logging, add new fields, shorten wait time for records, add page counter --- services/bots/AbstractBot.ts | 6 ++- services/bots/Analytics.ts | 81 ++++++++++++++++++++---------------- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index ccc6fb5..267200a 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1496,15 +1496,17 @@ abstract class AbstractBot { console.log("START DATE:",startDate); console.log("END DATE:",endDate); try { + let recordsPerRequest = 50; let keepRunning = true; let i = 1; let rows: any = []; while(keepRunning = true){ - const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage=50"+"&pageno="+i, this.axiosConfig)) + const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig)) .data; if (orders.rows.length > 0){ + console.log("page:",i," out of:",orders.rows[0].nbrof_rows/recordsPerRequest); rows = rows.concat(orders.rows); - utils.sleep(50); + utils.sleep(10); i ++; } else { keepRunning = false; diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts index 298dc05..6c01c5f 100644 --- a/services/bots/Analytics.ts +++ b/services/bots/Analytics.ts @@ -43,56 +43,65 @@ class Analytics extends AbstractBot { } runAnalytics (filledOrders: any) { - let totalCost = 0; - let totalSold = 0; - let qtyOutstanding = 0; - let totalFees = 0; - let makerBuysQty = 0; - let makerBuysAmt = 0; - let makerSellsQty = 0; - let makerSellsAmt = 0; - let takerBuysQty = 0; - let takerBuysAmt = 0; - let takerSellsQty = 0; - let takerSellsAmt = 0; - let totalVolumeQuote = 0; - let totalVolumeBase = 0; - let avgBuyPrice = 0; - let avgSellPrice = 0; + let data: any = {}; + data.totalCost = 0; + data.totalSold = 0; + data.qtyOutstanding = 0; + data.totalFees = 0; + data.makerBuysQty = 0; + data.makerBuysAmt = 0; + data.makerSellsQty = 0; + data.makerSellsAmt = 0; + data.takerBuysQty = 0; + data.takerBuysAmt = 0; + data.takerSellsQty = 0; + data.takerSellsAmt = 0; + data.totalVolumeQuote = 0; + data.totalVolumeBase = 0; + data.buyFillsMaker = 0; + data.askFillsMaker = 0; + data.buyFillsTaker = 0; + data.askFillsTaker = 0; filledOrders.forEach((e:any) => { if (e.type2 == 2 || e.type2 == 3){ if (e.side == 0){ - qtyOutstanding += parseFloat(e.quantityfilled); + data.qtyOutstanding += parseFloat(e.quantityfilled); let fee = e.totalfee * e.price; - totalFees += fee; - totalCost += e.quantityfilled * e.price; + data.totalFees += fee; + data.totalCost += e.quantityfilled * e.price; if (e.type2 == 2){ - takerBuysAmt += e.quantityfilled * e.price; - takerBuysQty += parseFloat(e.quantityfilled); + data.takerBuysAmt += e.quantityfilled * e.price; + data.takerBuysQty += parseFloat(e.quantityfilled); + data.buyFillsMaker ++; } else { - makerBuysAmt += e.quantityfilled * e.price; - makerBuysQty += parseFloat(e.quantityfilled); + data.makerBuysAmt += e.quantityfilled * e.price; + data.makerBuysQty += parseFloat(e.quantityfilled); + data.buyFillsTaker ++; } } else if (e.side == 1){ - qtyOutstanding-=parseFloat(e.quantityfilled); - totalFees += parseFloat(e.totalfee); - totalSold += e.quantityfilled * e.price + data.qtyOutstanding-=parseFloat(e.quantityfilled); + data.totalFees += parseFloat(e.totalfee); + data.totalSold += e.quantityfilled * e.price if (e.type2 == 2){ - takerSellsAmt += e.quantityfilled * e.price; - takerSellsQty += parseFloat(e.quantityfilled); + data.takerSellsAmt += e.quantityfilled * e.price; + data.takerSellsQty += parseFloat(e.quantityfilled); + data.askFillsMaker ++; } else { - makerSellsAmt += e.quantityfilled * e.price; - takerSellsQty += parseFloat(e.quantityfilled); + data.makerSellsAmt += e.quantityfilled * e.price; + data.takerSellsQty += parseFloat(e.quantityfilled); + data.askFillsTaker ++; } } } - totalVolumeBase += e.quantityFilled; - totalVolumeQuote += e.quantityFilled * e.price; + data.totalVolumeBase += parseFloat(e.quantityFilled); + data.totalVolumeQuote += e.quantityFilled * e.price; }); - avgBuyPrice = (takerBuysAmt+makerBuysAmt)/(takerBuysQty+makerBuysQty); - avgSellPrice = (takerSellsAmt+makerSellsAmt)/(takerSellsQty+makerSellsQty); - - console.log("AVG BUY:",avgBuyPrice, "AVG SELL:", avgSellPrice,"QTY OUTSTANDING:",qtyOutstanding,"MAKER BUYS AMT:", makerBuysAmt, "MAKER SELLS AMT:",makerSellsAmt, "TAKER BUYS AMT:", takerBuysAmt, "TAKER SELLS AMT:",takerSellsAmt, "TotalVolumeBase:",totalVolumeBase,"TotalVolumeQuote:",totalVolumeQuote, "TOTAL FEES:", totalFees); + data.avgBuyPrice = (data.takerBuysAmt+data.makerBuysAmt)/(data.takerBuysQty+data.makerBuysQty); + data.avgSellPrice = (data.takerSellsAmt+data.makerSellsAmt)/(data.takerSellsQty+data.makerSellsQty); + data.avgMakerBuyPrice = (data.makerBuysAmt)/(data.makerBuysQty); + data.avgMakerSellPrice = (data.makerSellsAmt)/(data.makerSellsQty); + console.log(data); + // console.log("AVG BUY:",avgBuyPrice, "AVG SELL:", avgSellPrice,"QTY OUTSTANDING:",qtyOutstanding,"MAKER BUYS AMT:", makerBuysAmt, "MAKER SELLS AMT:",makerSellsAmt, "TAKER BUYS AMT:", takerBuysAmt, "TAKER SELLS AMT:",takerSellsAmt, "TotalVolumeBase:",totalVolumeBase,"TotalVolumeQuote:",totalVolumeQuote, "TOTAL FEES:", totalFees); } async startOrderUpdater() { From 83d5d932dcb03c1af78e0434954b9c6ec92311c2 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 10:40:08 -0600 Subject: [PATCH 147/173] remove wait time --- services/bots/AbstractBot.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 267200a..787a3ef 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1504,9 +1504,8 @@ abstract class AbstractBot { const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig)) .data; if (orders.rows.length > 0){ - console.log("page:",i," out of:",orders.rows[0].nbrof_rows/recordsPerRequest); + console.log("page:",i," out of:",orders.rows[0].nbrof_rows/Math.ceil(recordsPerRequest)); rows = rows.concat(orders.rows); - utils.sleep(10); i ++; } else { keepRunning = false; From 0143f2e9bb2d2f3b395c7d4e13f9ba55d705c928 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 10:42:31 -0600 Subject: [PATCH 148/173] change number of rows logic --- services/bots/AbstractBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 787a3ef..106c8c9 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1496,7 +1496,7 @@ abstract class AbstractBot { console.log("START DATE:",startDate); console.log("END DATE:",endDate); try { - let recordsPerRequest = 50; + let recordsPerRequest = 200; let keepRunning = true; let i = 1; let rows: any = []; @@ -1504,7 +1504,7 @@ abstract class AbstractBot { const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig)) .data; if (orders.rows.length > 0){ - console.log("page:",i," out of:",orders.rows[0].nbrof_rows/Math.ceil(recordsPerRequest)); + console.log("page:",i," out of:",orders.rows[0].nbrof_rows); rows = rows.concat(orders.rows); i ++; } else { From d5720f91c96311e2d31b40787bb5d0fca7240013 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 10:44:10 -0600 Subject: [PATCH 149/173] change counter logic --- services/bots/AbstractBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 106c8c9..93d0800 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1496,7 +1496,7 @@ abstract class AbstractBot { console.log("START DATE:",startDate); console.log("END DATE:",endDate); try { - let recordsPerRequest = 200; + let recordsPerRequest = 100; let keepRunning = true; let i = 1; let rows: any = []; @@ -1504,7 +1504,7 @@ abstract class AbstractBot { const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig)) .data; if (orders.rows.length > 0){ - console.log("page:",i," out of:",orders.rows[0].nbrof_rows); + console.log("page:",i," out of:",Math.ceil(orders.rows[0].nbrof_rows/orders.rows.length)); rows = rows.concat(orders.rows); i ++; } else { From b3b95991642244a7de963c3de06f254d3019d380 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 11:17:50 -0600 Subject: [PATCH 150/173] use promises instead of waiting for each set of records to come back --- services/bots/AbstractBot.ts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 93d0800..002cfef 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1496,22 +1496,24 @@ abstract class AbstractBot { console.log("START DATE:",startDate); console.log("END DATE:",endDate); try { - let recordsPerRequest = 100; - let keepRunning = true; + let recordsPerRequest = 20; + let totalRecords = 200; let i = 1; + let promises:any = []; let rows: any = []; - while(keepRunning = true){ - const orders: any = (await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig)) - .data; - if (orders.rows.length > 0){ - console.log("page:",i," out of:",Math.ceil(orders.rows[0].nbrof_rows/orders.rows.length)); - rows = rows.concat(orders.rows); - i ++; - } else { - keepRunning = false; - return rows; - } + let record = await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig); + totalRecords = record.data.rows[0].nbrof_rows; + console.log("total Records:",totalRecords); + while(i <= Math.ceil(totalRecords/recordsPerRequest)){ + await new Promise(resolve => setTimeout(resolve, 100)); + promises.push(axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig)); + i++ } + const records = await Promise.all(promises); + records.forEach((e)=>{ + rows = rows.concat(e.data.rows); + }) + return rows; } catch (error: any) { this.logger.error(`${this.instanceName} ${error}`); } From e2cbb92c3571ce4280533a28734d84962a5f7d26 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 11:20:55 -0600 Subject: [PATCH 151/173] fix typo --- services/bots/Analytics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts index 6c01c5f..cc63da6 100644 --- a/services/bots/Analytics.ts +++ b/services/bots/Analytics.ts @@ -88,7 +88,7 @@ class Analytics extends AbstractBot { data.askFillsMaker ++; } else { data.makerSellsAmt += e.quantityfilled * e.price; - data.takerSellsQty += parseFloat(e.quantityfilled); + data.makerSellsQty += parseFloat(e.quantityfilled); data.askFillsTaker ++; } } From b334df8dfa8e5da3cc90a3d147be669c5f5c45f2 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 11:24:55 -0600 Subject: [PATCH 152/173] correct maker and taker fills --- services/bots/Analytics.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts index cc63da6..397edf5 100644 --- a/services/bots/Analytics.ts +++ b/services/bots/Analytics.ts @@ -72,11 +72,11 @@ class Analytics extends AbstractBot { if (e.type2 == 2){ data.takerBuysAmt += e.quantityfilled * e.price; data.takerBuysQty += parseFloat(e.quantityfilled); - data.buyFillsMaker ++; + data.buyFillsTaker ++; } else { data.makerBuysAmt += e.quantityfilled * e.price; data.makerBuysQty += parseFloat(e.quantityfilled); - data.buyFillsTaker ++; + data.buyFillsMaker ++; } } else if (e.side == 1){ data.qtyOutstanding-=parseFloat(e.quantityfilled); @@ -85,11 +85,11 @@ class Analytics extends AbstractBot { if (e.type2 == 2){ data.takerSellsAmt += e.quantityfilled * e.price; data.takerSellsQty += parseFloat(e.quantityfilled); - data.askFillsMaker ++; + data.askFillsTaker ++; } else { data.makerSellsAmt += e.quantityfilled * e.price; data.makerSellsQty += parseFloat(e.quantityfilled); - data.askFillsTaker ++; + data.askFillsMaker ++; } } } From 4475570966aad8f5a2e9c4bc22530ffaaaa56248 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 13:05:18 -0600 Subject: [PATCH 153/173] try to work around max records returned --- services/bots/AbstractBot.ts | 30 +++++++++++++++++++++++++++--- services/bots/Analytics.ts | 30 ++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 002cfef..e52aaff 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1495,24 +1495,48 @@ abstract class AbstractBot { console.log("START DATE:",startDate); console.log("END DATE:",endDate); + let rows: any = []; + let tries = 0; + try { + let keepRunning = true; + while (keepRunning){ + let newRows = await this.getRecords(startDate,endDate); + if (tries != 0 && newRows[newRows.length-1].update_ts == rows[rows.length-1].update_ts){ + return rows; + } else { + tries ++ + if (tries > 3){ + process.exit(2); + } + rows = rows.concat(newRows); + endDate = rows[rows.length-1].update_ts + } + } + } catch (error: any) { + this.logger.error(`${this.instanceName} ${error}`); + } + } + + async getRecords(startDate:string,endDate:string){ try { let recordsPerRequest = 20; let totalRecords = 200; let i = 1; let promises:any = []; let rows: any = []; - let record = await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig); + let record = await axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage=20"+"&pageno="+i, this.axiosConfig); totalRecords = record.data.rows[0].nbrof_rows; console.log("total Records:",totalRecords); - while(i <= Math.ceil(totalRecords/recordsPerRequest)){ + while(i <= Math.ceil(totalRecords/20)){ await new Promise(resolve => setTimeout(resolve, 100)); - promises.push(axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage="+recordsPerRequest+"&pageno="+i, this.axiosConfig)); + promises.push(axios.get(signedApiUrl + "orders?pair=" + this.tradePairIdentifier + "&category=1" + "&periodfrom=" + startDate + "&periodto="+endDate + "&itemsperpage=20"+"&pageno="+i, this.axiosConfig)); i++ } const records = await Promise.all(promises); records.forEach((e)=>{ rows = rows.concat(e.data.rows); }) + return rows; } catch (error: any) { this.logger.error(`${this.instanceName} ${error}`); diff --git a/services/bots/Analytics.ts b/services/bots/Analytics.ts index 397edf5..d9fee71 100644 --- a/services/bots/Analytics.ts +++ b/services/bots/Analytics.ts @@ -8,6 +8,9 @@ import NewOrder from "./classes"; class Analytics extends AbstractBot { protected startDate: number = 0; protected endDate: number = 0; + protected marketPrice = new BigNumber(0); + protected baseUsd = 0; + protected quoteUsd = 0; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -24,6 +27,7 @@ class Analytics extends AbstractBot { async initialize(): Promise { const initializing = await super.initialize(); if (initializing) { + await this.getNewMarketPrice(); let startDate = Date.now()-(86400000*30); let endDate = Date.now(); if (this.startDate){ @@ -107,9 +111,31 @@ class Analytics extends AbstractBot { async startOrderUpdater() { } - // Update the marketPrice from an outside source + + // Update the marketPrice from price feed bot async getNewMarketPrice() { - return new BigNumber(0); + try { + let response = await axios.get('http://localhost:3000/prices'); + let prices = response.data; + + + if (this.base == "sAVAX"){ + this.quoteUsd = prices[this.quote+'-USD']; + this.baseUsd = prices['sAVAX-AVAX'] * this.quoteUsd; + } else { + this.baseUsd = prices[this.base+'-USD']; + this.quoteUsd = prices[this.quote+'-USD']; + } + if (this.baseUsd && this.quoteUsd){ + this.marketPrice = new BigNumber(this.baseUsd/this.quoteUsd); + console.log("new market Price:",this.marketPrice.toNumber()); + } else { + throw 'trouble getting base or quote prices' + } + } catch (error: any) { + this.logger.error(`${this.instanceName} Error during getNewMarketPrice`, error); + } + return this.marketPrice; } getPrice(side: number): BigNumber { From ee9afaa01e73e2bf3e454dc90386b1c75bb93be5 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 13:39:46 -0600 Subject: [PATCH 154/173] add shift --- services/bots/AbstractBot.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index e52aaff..8eabe98 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1504,6 +1504,9 @@ abstract class AbstractBot { if (tries != 0 && newRows[newRows.length-1].update_ts == rows[rows.length-1].update_ts){ return rows; } else { + if (tries > 0 && newRows[0].update_ts == rows[rows.length-1].update_ts){ + newRows.shift(); + } tries ++ if (tries > 3){ process.exit(2); From 2f289a0fb3a5c2d71868d9a09ba9f449cc244409 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 13:43:32 -0600 Subject: [PATCH 155/173] remove limit --- services/bots/AbstractBot.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 8eabe98..4bfe299 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1508,9 +1508,7 @@ abstract class AbstractBot { newRows.shift(); } tries ++ - if (tries > 3){ - process.exit(2); - } + process.exit(2); rows = rows.concat(newRows); endDate = rows[rows.length-1].update_ts } From 78d5bddfc16258ac2752a80b4ebef802357fa622 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Wed, 29 Nov 2023 13:44:44 -0600 Subject: [PATCH 156/173] remove process exit --- services/bots/AbstractBot.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 4bfe299..dd6c226 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1508,7 +1508,6 @@ abstract class AbstractBot { newRows.shift(); } tries ++ - process.exit(2); rows = rows.concat(newRows); endDate = rows[rows.length-1].update_ts } From 103923454a30e3777758edb1193f5639ddefe480 Mon Sep 17 00:00:00 2001 From: Beastlorion Date: Sat, 2 Dec 2023 13:31:05 -0600 Subject: [PATCH 157/173] fix bug triggered when using negative spreads --- services/bots/MarketMakerBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index c2c0ff8..540a0d2 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -143,8 +143,8 @@ class MarketMakerBot extends AbstractBot { let startingAskPrice = startingAskPriceBG.toNumber(); // if the bid and ask are the same price, increase the ask by one tick - if (startingBidPrice == startingAskPrice){ - startingAskPrice += this.getIncrement(); + if (startingBidPrice >= startingAskPrice){ + startingAskPrice = startingBidPrice + this.getIncrement(); } // if takerEnabled config is true, these prices will be used to determine what price to place taker orders at. From f1d96ab1d0323df77b1bbdf073600a731f856a29 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 23 Jan 2024 18:19:31 +0700 Subject: [PATCH 158/173] use while loop and async instead of calling recursively in finally --- services/bots/AbstractBot.ts | 2 +- services/bots/MarketMakerBot.ts | 47 +++++++++++++++------------------ 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index dd6c226..23b0dce 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -2038,7 +2038,7 @@ abstract class AbstractBot { let currentBestAskResponse = await this.orderBooks.getTopOfTheBook(this.orderBookID1); let currentBestBid = new BigNumber(currentBestBidResponse.price.toString())//.dp(this.quoteDisplayDecimals); let currentBestAsk = new BigNumber(currentBestAskResponse.price.toString())//.dp(this.quoteDisplayDecimals); - if (this.tradePairIdentifier=="sAVAX/AVAX"){ + if (this.tradePairIdentifier=="sAVAX/AVAX" || this.tradePairIdentifier=="COQ/AVAX"){ this.currentBestBid = currentBestBid.div("1000000000000000000").toNumber() this.currentBestAsk = currentBestAsk.div("1000000000000000000").toNumber() } else { diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 540a0d2..d7e266a 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -64,6 +64,8 @@ class MarketMakerBot extends AbstractBot { // await this.getBestOrders(); this.interval = 10000; //Min 8 seconds + //Cancel any remaining orders + await this.cancelOrderList([], 100); // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); @@ -80,11 +82,6 @@ class MarketMakerBot extends AbstractBot { if (this.portfolioRebalanceAtStart){ await utils.sleep(30000); } - - this.logger.debug(`${JSON.stringify(this.getOrderBook())}`); - - //Cancel any remaining orders - await this.cancelOrderList([], 100); if (this.baseUsd && this.quoteUsd){ // ------------ Create and Send Initial Order List ------------ // @@ -98,10 +95,15 @@ class MarketMakerBot extends AbstractBot { // ------------ Begin Order Updater ------------ // - this.orderUpdater = setTimeout(()=>{ - this.lastMarketPrice = this.marketPrice; - this.updateOrders(); - }, this.interval); + while (true){ + await this.getNewMarketPrice(); + let placedOrders: boolean = await this.updateOrders(); + if (placedOrders){ + await new Promise(resolve => setTimeout(resolve, this.interval)); + } else { + await new Promise(resolve => setTimeout(resolve, 2000)); + } + } } else { console.log("MISSING PRICE DATA - baseUsd:",this.baseUsd, " quoteUsd: ",this.quoteUsd, "Wait 10 seconds then try again"); await utils.sleep(10000); @@ -114,10 +116,7 @@ class MarketMakerBot extends AbstractBot { } // this is the meat and potatoes of the bot. It will repeatedly call itself to refresh orders if the price is outside the refreshOrderTolerance spread, or too much time has passed since the last update. - async updateOrders() { - if (this.orderUpdater != undefined) { - clearTimeout(this.orderUpdater); - } + async updateOrders():Promise { try { if (this.status && (this.retrigger || (Date.now() - this.lastUpdate)/1000 > 600 || this.marketPrice.toNumber()this.lastMarketPrice.toNumber()*(1+parseFloat(this.refreshOrderTolerance)))){ @@ -257,20 +256,15 @@ class MarketMakerBot extends AbstractBot { this.lastMarketPrice = this.marketPrice; this.retrigger = false; } - - } + return true + } else { + return false; + } } catch (error) { this.logger.error(`${this.instanceName} Error in UpdateOrders`, error); - this.cleanUpAndExit(); - } finally { - //Update orders again after interval - this.orderUpdater = setTimeout(async ()=>{ - if (this.status){ - await Promise.all([this.getNewMarketPrice()]); - this.timer = 2000; - this.updateOrders(); - } - }, this.timer); + await this.cleanUpAndExit(); + this.status = false; + return false } } @@ -492,6 +486,9 @@ class MarketMakerBot extends AbstractBot { if (this.base == "sAVAX"){ this.quoteUsd = prices[this.quote+'-USD']; this.baseUsd = prices['sAVAX-AVAX'] * this.quoteUsd; + } else if (this.base == "COQ") { + this.quoteUsd = prices[this.quote+'-USD']; + this.baseUsd = prices['COQ-AVAX'] * this.quoteUsd; } else { this.baseUsd = prices[this.base+'-USD']; this.quoteUsd = prices[this.quote+'-USD']; From 1787f35b0b82489bc67098098cc1681f6be07092 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 13 Feb 2024 11:53:28 +0700 Subject: [PATCH 159/173] remove unused variable from abstract bot --- services/bots/AbstractBot.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 23b0dce..2b1b4ae 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -30,7 +30,6 @@ abstract class AbstractBot { protected initialized = false; protected account = "0x"; - protected balanceId: number | undefined; protected orderCount = 0; protected config: any; protected pairObject: any | undefined; @@ -323,7 +322,6 @@ abstract class AbstractBot { async start() { if (this.initialized && !this.status) { this.status = true; - this.balanceId = undefined; const balancesRefreshed = await this.doInitialFunding(); this.saveBalancestoDb(balancesRefreshed); From 2680b57d55ad5213ff5255620d1efbf93ef6b4ba Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 13 Feb 2024 19:52:26 +0700 Subject: [PATCH 160/173] fix readme typo. Change defensiveSkew logic --- README.md | 2 +- services/bots/MarketMakerBot.ts | 15 ++++++++------- services/bots/MarketMakerBotOrderLists.ts | 15 ++++++++------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2d4e7ae..04a4e6c 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Paste this into your .env.fuji with your private key and address. PLEASE USE A T "tolerance": "0.75" } } - }, + } } ``` diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index d7e266a..b607971 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -451,9 +451,10 @@ class MarketMakerBot extends AbstractBot { slip = this.lastChange/2; } let defensiveSkew = 0; - let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); - if (multiple >= 2 && this.defensiveSkew){ - defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) + let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*20; + if (multiple > 0 && this.defensiveSkew){ + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); } let bidSpread = this.bidSpread + defensiveSkew + slip; console.log("Bid Spread:",bidSpread); @@ -466,10 +467,10 @@ class MarketMakerBot extends AbstractBot { slip = this.lastChange - this.refreshOrderTolerance; } let defensiveSkew = 0; - let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); - if (1/multiple > 2 && this.defensiveSkew){ - multiple = 1/multiple; - defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) + let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*-20; + if (multiple > 0 && this.defensiveSkew){ + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); } let askSpread = this.askSpread + defensiveSkew + slip; console.log("Ask Spread:",askSpread); diff --git a/services/bots/MarketMakerBotOrderLists.ts b/services/bots/MarketMakerBotOrderLists.ts index 590f032..9f66390 100644 --- a/services/bots/MarketMakerBotOrderLists.ts +++ b/services/bots/MarketMakerBotOrderLists.ts @@ -291,9 +291,10 @@ class MarketMakerBot extends AbstractBot { slip = this.lastChange/2; } let defensiveSkew = 0; - let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); - if (multiple >= 2 && this.defensiveSkew){ - defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) + let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*20; + if (multiple > 0 && this.defensiveSkew){ + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); } let bidSpread = this.bidSpread + defensiveSkew + slip; console.log("Bid Spread:",bidSpread); @@ -306,10 +307,10 @@ class MarketMakerBot extends AbstractBot { slip = this.lastChange - this.refreshOrderTolerance; } let defensiveSkew = 0; - let multiple = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/parseFloat(this.contracts[this.quote].portfolioTot); - if (1/multiple > 2 && this.defensiveSkew){ - multiple = 1/multiple; - defensiveSkew = multiple < 6 ? this.defensiveSkew * Math.floor(multiple-1) : this.defensiveSkew * 5 + let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) + let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*-20; + if (multiple > 0 && this.defensiveSkew){ + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); } let askSpread = this.askSpread + defensiveSkew + slip; console.log("Ask Spread:",askSpread); From afce06630be71d831a2bf2e0b1ae5c9c9bfcdd4a Mon Sep 17 00:00:00 2001 From: beastlorion Date: Tue, 13 Feb 2024 20:04:15 +0700 Subject: [PATCH 161/173] fix bug in new defensiveSkew --- services/bots/MarketMakerBot.ts | 4 ++-- services/bots/MarketMakerBotOrderLists.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index b607971..b362e82 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -454,7 +454,7 @@ class MarketMakerBot extends AbstractBot { let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*20; if (multiple > 0 && this.defensiveSkew){ - defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(8)); } let bidSpread = this.bidSpread + defensiveSkew + slip; console.log("Bid Spread:",bidSpread); @@ -470,7 +470,7 @@ class MarketMakerBot extends AbstractBot { let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*-20; if (multiple > 0 && this.defensiveSkew){ - defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(8)); } let askSpread = this.askSpread + defensiveSkew + slip; console.log("Ask Spread:",askSpread); diff --git a/services/bots/MarketMakerBotOrderLists.ts b/services/bots/MarketMakerBotOrderLists.ts index 9f66390..a747ffd 100644 --- a/services/bots/MarketMakerBotOrderLists.ts +++ b/services/bots/MarketMakerBotOrderLists.ts @@ -294,7 +294,7 @@ class MarketMakerBot extends AbstractBot { let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*20; if (multiple > 0 && this.defensiveSkew){ - defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(8)); } let bidSpread = this.bidSpread + defensiveSkew + slip; console.log("Bid Spread:",bidSpread); @@ -310,7 +310,7 @@ class MarketMakerBot extends AbstractBot { let totalFunds = parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()+parseFloat(this.contracts[this.quote].portfolioTot) let multiple = ((parseFloat(this.contracts[this.base].portfolioTot)*this.marketPrice.toNumber()/totalFunds)-.5)*-20; if (multiple > 0 && this.defensiveSkew){ - defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(2)); + defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(8)); } let askSpread = this.askSpread + defensiveSkew + slip; console.log("Ask Spread:",askSpread); From ed15f2226606b43b0e0beb3846fa86cf063470c7 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Wed, 6 Mar 2024 23:22:37 +0700 Subject: [PATCH 162/173] add tires to cancel all to avoid spamming --- services/bots/AbstractBot.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 2b1b4ae..f404d54 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -1198,7 +1198,10 @@ abstract class AbstractBot { } } - async cancelOrderList(orderIds: string[] = [], nbrofOrderstoCancel = 30) { + async cancelOrderList(orderIds: string[] = [], tries = 0) { + if (tries > 2){ + return + } try { let idsToCancel: string[] = []; if (orderIds.length === 0) { @@ -1208,10 +1211,6 @@ abstract class AbstractBot { idsToCancel.push(order.id); } i++; - if (i >= nbrofOrderstoCancel) { - // More than xx orders in a cancel will run out of gas - break; - } } } else { for (let i = 0; i < orderIds.length; i++){ @@ -1266,7 +1265,7 @@ abstract class AbstractBot { //this.logger.error(`${this.instanceName} Error during CancelAll`, error); setTimeout(async()=>{ await this.correctNonce(this.contracts["SubNetProvider"]); - this.cancelOrderList(orderIds); + this.cancelOrderList(orderIds,tries + 1); },1000); } } From eaaa4c3fe3c2d3b07aa91a898f7c6e16806c81f2 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 16 Mar 2024 21:45:07 +0700 Subject: [PATCH 163/173] don't set lastChange if lastMarketPrice was 0 --- services/bots/MarketMakerBot.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index b362e82..59e165c 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -134,7 +134,9 @@ class MarketMakerBot extends AbstractBot { // updates balances, gets best bids and asks, and corrects the nonce await Promise.all([this.getBalances(),this.getBestOrders(),this.correctNonce(this.contracts["SubNetProvider"]),this.processOpenOrders()]); - this.lastChange = Math.abs(this.marketPrice.toNumber()-this.lastMarketPrice.toNumber())/this.marketPrice.toNumber(); + if (this.lastMarketPrice.toNumber() != 0){ + this.lastChange = Math.abs(this.marketPrice.toNumber()-this.lastMarketPrice.toNumber())/this.marketPrice.toNumber(); + } let startingBidPriceBG = this.marketPrice.multipliedBy(1-this.getBidSpread()).dp(this.quoteDisplayDecimals, BigNumber.ROUND_DOWN); let startingBidPrice = startingBidPriceBG.toNumber(); From fda7832a382693b54a81dde38f162e9133da0be5 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 16 Mar 2024 23:36:28 +0700 Subject: [PATCH 164/173] add support for volatility spreads --- services/bots/MarketMakerBot.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 59e165c..f1ce176 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -30,6 +30,8 @@ class MarketMakerBot extends AbstractBot { protected useRetrigger = false; protected useIndependentLevels: boolean = false; protected independentLevels: any; + protected addVolSpread: boolean = false; + protected volSpread = 0; constructor(botId: number, pairStr: string, privateKey: string) { super(botId, pairStr, privateKey); @@ -50,6 +52,7 @@ class MarketMakerBot extends AbstractBot { this.useRetrigger = this.config.useRetrigger this.useIndependentLevels = this.config.useIndependentLevels this.independentLevels = this.config.independentLevels; + this.addVolSpread = this.config.addVolSpread; console.log('this.independentLevels',this.independentLevels) } @@ -458,7 +461,7 @@ class MarketMakerBot extends AbstractBot { if (multiple > 0 && this.defensiveSkew){ defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(8)); } - let bidSpread = this.bidSpread + defensiveSkew + slip; + let bidSpread = this.bidSpread + defensiveSkew + slip + (this.volSpread/2); console.log("Bid Spread:",bidSpread); return bidSpread; } @@ -474,13 +477,16 @@ class MarketMakerBot extends AbstractBot { if (multiple > 0 && this.defensiveSkew){ defensiveSkew = parseFloat((this.defensiveSkew * multiple).toFixed(8)); } - let askSpread = this.askSpread + defensiveSkew + slip; + let askSpread = this.askSpread + defensiveSkew + slip + (this.volSpread/2); console.log("Ask Spread:",askSpread); return askSpread; } // Update the marketPrice from price feed bot async getNewMarketPrice() { + if (this.addVolSpread){ + this.getVolSpread(); + } try { let response = await axios.get('http://localhost:3000/prices'); let prices = response.data; @@ -507,6 +513,16 @@ class MarketMakerBot extends AbstractBot { } return this.marketPrice; } + async getVolSpread(){ + try { + let response = await axios.get('http://localhost:3000/spreads'); + let spreads = response.data; + this.volSpread = spreads[this.base + '-USD'] + console.log("VOLSPREAD:", this.volSpread) + } catch { + console.log("error during getVolSpreads") + } + } refreshLevel(level:number,isBid : boolean): boolean { if (level == 1 || !this.useIndependentLevels){ From 9ab60ca6fe847a179714f1c2881848adf061b62d Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 21 Mar 2024 10:46:28 +0000 Subject: [PATCH 165/173] fix cancelOrderList inputs --- services/bots/botLauncher.ts | 112 ++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 40 deletions(-) diff --git a/services/bots/botLauncher.ts b/services/bots/botLauncher.ts index 88e34e8..70183fc 100644 --- a/services/bots/botLauncher.ts +++ b/services/bots/botLauncher.ts @@ -1,40 +1,72 @@ -import { getConfig } from "../../config"; -import encrypter from "../EncryptionService"; -const BotFactory = require("./BotFactory.js"); - -function cleanUpAndExit(botLaunched: any) { - botLaunched?.cleanUpAndExit(); -} - -encrypter.setKey(getConfig("ENCYRPT_SECRET"), getConfig("ENCRYPT_SALT")); - -const privkey = encrypter.isKeyEncrypted(getConfig("private_key")) - ? encrypter.dencrypt(getConfig("private_key")) - : getConfig("private_key"); -const bot = BotFactory.createBot(getConfig("bot_type"), { botId: getConfig("bot_id"), pairStr: getConfig("pair"), privateKey: privkey }); -bot.initialize().then(() => { - bot.start(); -}); -// exit handler to remove all open buy and sell orders from all simulators -process.on("SIGINT", async () => { - // Needed for Local Windows Ctrl-C - cleanUpAndExit(bot); -}); - -process.on("exit", async () => { - cleanUpAndExit(bot); -}); - -process.on("SIGTERM", async () => { - //Needed for AWS - cleanUpAndExit(bot); -}); - -process.on("uncaughtException", (error) => { - console.log(`BotManager uncaughtException happened:`, error); -}); - -process.on("unhandledRejection", (error, promise) => { - console.log(`BotManager We forgot to handle a promise rejection here:`, promise); - console.log(`BotManager The error was:`, error); -}); +// Use this code snippet in your app. +// If you need more information about configurations or implementing the sample code, visit the AWS docs: +// https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started.html + + +import { getConfig } from "../../config"; +const BotFactory = require("./BotFactory.js"); +const config: any = getConfig(getConfig("pair")); + +function cleanUpAndExit(botLaunched: any) { + botLaunched?.cleanUpAndExit(); +} + +import { + SecretsManagerClient, + GetSecretValueCommand, +} from "@aws-sdk/client-secrets-manager"; + +const secret_name = config.secret_name; + +const client = new SecretsManagerClient({ + region: "ap-southeast-1", +}); + +client.send( + new GetSecretValueCommand({ + SecretId: secret_name, + VersionStage: "AWSCURRENT", // VersionStage defaults to AWSCURRENT if unspecified + }) + ).then((response)=>{ + + const secret: any = response.SecretString; + + // Your code goes here + + const privkey = JSON.parse(secret)["dexalot_mm_"+getConfig("pair")]; + const bot = BotFactory.createBot(getConfig("bot_type"), { botId: getConfig("bot_id"), pairStr: getConfig("pair"), privateKey: privkey }); + bot.initialize().then(() => { + bot.start(); + }); + // exit handler to remove all open buy and sell orders from all simulators + process.on("SIGINT", async () => { + // Needed for Local Windows Ctrl-C + cleanUpAndExit(bot); + }); + + process.on("exit", async () => { + cleanUpAndExit(bot); + }); + + process.on("SIGTERM", async () => { + //Needed for AWS + cleanUpAndExit(bot); + }); + + process.on("uncaughtException", (error) => { + console.log(`BotManager uncaughtException happened:`, error); + bot.cancelOrderList([], 100); + }); + + process.on("unhandledRejection", (error, promise) => { + console.log(`BotManager We forgot to handle a promise rejection here:`, promise); + console.log(`BotManager The error was:`, error); + bot.cancelOrderList([], 100); + }); + + + }).catch((error) => { + // For a list of exceptions thrown, see + // https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html + throw error; +}) From 7fca9799673c7b08ace9a2d4ea17d4fd3832313a Mon Sep 17 00:00:00 2001 From: beastlorion Date: Thu, 21 Mar 2024 17:55:15 +0700 Subject: [PATCH 166/173] undo previous commit and fix cancelAll inputs --- services/bots/AbstractBot.ts | 2 +- services/bots/MarketMakerBot.ts | 2 +- services/bots/botLauncher.ts | 86 +++++++++++---------------------- 3 files changed, 29 insertions(+), 61 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index f404d54..cc76652 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -356,7 +356,7 @@ abstract class AbstractBot { } setTimeout(async ()=> { await this.processOpenOrders(); - this.cancelOrderList([], 100) + this.cancelOrderList([]) .then(() => { this.logger.warn(`${this.instanceName} Waiting 5 seconds before removing order listeners"...`); setTimeout(async () => { diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index f1ce176..894386d 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -68,7 +68,7 @@ class MarketMakerBot extends AbstractBot { this.interval = 10000; //Min 8 seconds //Cancel any remaining orders - await this.cancelOrderList([], 100); + await this.cancelOrderList([]); // PNL TO KEEP TRACK OF PNL , FEE & TCOST etc //this.PNL = new PNL(getConfig('NODE_ENV_SETTINGS'), this.instanceName, this.base, this.quote, this.config, this.account); diff --git a/services/bots/botLauncher.ts b/services/bots/botLauncher.ts index 70183fc..e8564a6 100644 --- a/services/bots/botLauncher.ts +++ b/services/bots/botLauncher.ts @@ -1,72 +1,40 @@ -// Use this code snippet in your app. -// If you need more information about configurations or implementing the sample code, visit the AWS docs: -// https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started.html - - import { getConfig } from "../../config"; +import encrypter from "../EncryptionService"; const BotFactory = require("./BotFactory.js"); -const config: any = getConfig(getConfig("pair")); function cleanUpAndExit(botLaunched: any) { botLaunched?.cleanUpAndExit(); } -import { - SecretsManagerClient, - GetSecretValueCommand, -} from "@aws-sdk/client-secrets-manager"; +encrypter.setKey(getConfig("ENCYRPT_SECRET"), getConfig("ENCRYPT_SALT")); -const secret_name = config.secret_name; - -const client = new SecretsManagerClient({ - region: "ap-southeast-1", +const privkey = encrypter.isKeyEncrypted(getConfig("private_key")) + ? encrypter.dencrypt(getConfig("private_key")) + : getConfig("private_key"); +const bot = BotFactory.createBot(getConfig("bot_type"), { botId: getConfig("bot_id"), pairStr: getConfig("pair"), privateKey: privkey }); +bot.initialize().then(() => { + bot.start(); +}); +// exit handler to remove all open buy and sell orders from all simulators +process.on("SIGINT", async () => { + // Needed for Local Windows Ctrl-C + cleanUpAndExit(bot); }); -client.send( - new GetSecretValueCommand({ - SecretId: secret_name, - VersionStage: "AWSCURRENT", // VersionStage defaults to AWSCURRENT if unspecified - }) - ).then((response)=>{ - - const secret: any = response.SecretString; - - // Your code goes here - - const privkey = JSON.parse(secret)["dexalot_mm_"+getConfig("pair")]; - const bot = BotFactory.createBot(getConfig("bot_type"), { botId: getConfig("bot_id"), pairStr: getConfig("pair"), privateKey: privkey }); - bot.initialize().then(() => { - bot.start(); - }); - // exit handler to remove all open buy and sell orders from all simulators - process.on("SIGINT", async () => { - // Needed for Local Windows Ctrl-C - cleanUpAndExit(bot); - }); - - process.on("exit", async () => { - cleanUpAndExit(bot); - }); - - process.on("SIGTERM", async () => { - //Needed for AWS - cleanUpAndExit(bot); - }); - - process.on("uncaughtException", (error) => { - console.log(`BotManager uncaughtException happened:`, error); - bot.cancelOrderList([], 100); - }); +process.on("exit", async () => { + cleanUpAndExit(bot); +}); - process.on("unhandledRejection", (error, promise) => { - console.log(`BotManager We forgot to handle a promise rejection here:`, promise); - console.log(`BotManager The error was:`, error); - bot.cancelOrderList([], 100); - }); +process.on("SIGTERM", async () => { + //Needed for AWS + cleanUpAndExit(bot); +}); +process.on("uncaughtException", (error) => { + console.log(`BotManager uncaughtException happened:`, error); +}); - }).catch((error) => { - // For a list of exceptions thrown, see - // https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html - throw error; -}) +process.on("unhandledRejection", (error, promise) => { + console.log(`BotManager We forgot to handle a promise rejection here:`, promise); + console.log(`BotManager The error was:`, error); +}); \ No newline at end of file From f00bc0e5f9f245f0e13a2783820724351dd93ad4 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 22 Mar 2024 21:36:57 +0700 Subject: [PATCH 167/173] add support for memecoins --- services/bots/AbstractBot.ts | 2 +- services/bots/MarketMakerBot.ts | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index cc76652..57a2458 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -2035,7 +2035,7 @@ abstract class AbstractBot { let currentBestAskResponse = await this.orderBooks.getTopOfTheBook(this.orderBookID1); let currentBestBid = new BigNumber(currentBestBidResponse.price.toString())//.dp(this.quoteDisplayDecimals); let currentBestAsk = new BigNumber(currentBestAskResponse.price.toString())//.dp(this.quoteDisplayDecimals); - if (this.tradePairIdentifier=="sAVAX/AVAX" || this.tradePairIdentifier=="COQ/AVAX"){ + if (this.quote == "AVAX"){ this.currentBestBid = currentBestBid.div("1000000000000000000").toNumber() this.currentBestAsk = currentBestAsk.div("1000000000000000000").toNumber() } else { diff --git a/services/bots/MarketMakerBot.ts b/services/bots/MarketMakerBot.ts index 894386d..ba2bccc 100644 --- a/services/bots/MarketMakerBot.ts +++ b/services/bots/MarketMakerBot.ts @@ -492,12 +492,9 @@ class MarketMakerBot extends AbstractBot { let prices = response.data; - if (this.base == "sAVAX"){ + if (this.base == "sAVAX" || this.base == "COQ" || this.base == "NOCHILL" || this.base == "GEC" || this.base == "KIMBO" || this.base == "TECH" || this.base == "MEOW") { this.quoteUsd = prices[this.quote+'-USD']; - this.baseUsd = prices['sAVAX-AVAX'] * this.quoteUsd; - } else if (this.base == "COQ") { - this.quoteUsd = prices[this.quote+'-USD']; - this.baseUsd = prices['COQ-AVAX'] * this.quoteUsd; + this.baseUsd = prices[this.base+'-AVAX'] * this.quoteUsd; } else { this.baseUsd = prices[this.base+'-USD']; this.quoteUsd = prices[this.quote+'-USD']; From 5dd0bea5a3220830f63b85a1ac3132c5f090317c Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 5 Apr 2024 14:35:59 +0700 Subject: [PATCH 168/173] only use avalanche token contracts --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 57a2458..e7e3346 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -180,7 +180,7 @@ abstract class AbstractBot { } async getTokenDetail(symbol: string): Promise { - return this.tokenDetails.find((item: any) => item.symbol === symbol); + return this.tokenDetails.find((item: any) => item.symbol === symbol && item.env == "production-multi-avax"); } async setNonce(provider: string): Promise { From 3783f47aa38359bd9e7616a4a6adca4190ff6b59 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 5 Apr 2024 16:24:18 +0700 Subject: [PATCH 169/173] use avalanche environment --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index e7e3346..9569b96 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -172,7 +172,7 @@ abstract class AbstractBot { getEnvironment(envtype: string) { //mainnet, subnet - return this.environments.find((item: any) => item.type === envtype); + return this.environments.find((item: any) => item.type === envtype && item.env == "production-multi-avax"); } async getTokenDetails() { From bdc3370f2bc0569765e52ff7189afd95cee9fc65 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Fri, 5 Apr 2024 16:31:00 +0700 Subject: [PATCH 170/173] fix bug with environments selection --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 9569b96..aeabde4 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -172,7 +172,7 @@ abstract class AbstractBot { getEnvironment(envtype: string) { //mainnet, subnet - return this.environments.find((item: any) => item.type === envtype && item.env == "production-multi-avax"); + return this.environments.find((item: any) => item.type === envtype && (item.env == "production-multi-avax" || item.env == "production-multi-subnet")); } async getTokenDetails() { From bf00cea9a830e675be373f2fdc632fec9c795869 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Sat, 13 Apr 2024 17:47:26 +0700 Subject: [PATCH 171/173] fix cancelOrderList inputs in lists version --- services/bots/MarketMakerBotOrderLists.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/MarketMakerBotOrderLists.ts b/services/bots/MarketMakerBotOrderLists.ts index a747ffd..9f8c299 100644 --- a/services/bots/MarketMakerBotOrderLists.ts +++ b/services/bots/MarketMakerBotOrderLists.ts @@ -76,7 +76,7 @@ class MarketMakerBot extends AbstractBot { await this.correctNonce(this.contracts["SubNetProvider"]); //Cancel any remaining orders - await this.cancelOrderList([], 100); + await this.cancelOrderList([]); if (this.baseUsd && this.quoteUsd){ // ------------ Create and Send Initial Order List ------------ // @@ -123,7 +123,7 @@ class MarketMakerBot extends AbstractBot { this.lastChange = Math.abs(this.marketPrice.toNumber()-this.lastMarketPrice.toNumber())/this.marketPrice.toNumber(); // Cancel all orders, when finished, trigger the new order placement. - const promise = Promise.resolve(this.cancelOrderList([], 100)); + const promise = Promise.resolve(this.cancelOrderList([])); if (this.baseUsd && this.quoteUsd){ // ------------ Create new Order List ------------ // From 1db22e9a334f777a4512e3263e4c9933b911d8a0 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 15 Apr 2024 22:26:25 +0700 Subject: [PATCH 172/173] use subnet symbols for getTokenDetails --- services/bots/AbstractBot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index aeabde4..491936a 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -180,7 +180,7 @@ abstract class AbstractBot { } async getTokenDetail(symbol: string): Promise { - return this.tokenDetails.find((item: any) => item.symbol === symbol && item.env == "production-multi-avax"); + return this.tokenDetails.find((item: any) => item.subnet_symbol === symbol && item.env == "production-multi-avax"); } async setNonce(provider: string): Promise { From 0e92f2914dbfc347925ed7aa4b2fcac694716d17 Mon Sep 17 00:00:00 2001 From: beastlorion Date: Mon, 15 Apr 2024 23:05:03 +0700 Subject: [PATCH 173/173] use subnet symbols for balances --- services/bots/AbstractBot.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/bots/AbstractBot.ts b/services/bots/AbstractBot.ts index 491936a..85ac465 100644 --- a/services/bots/AbstractBot.ts +++ b/services/bots/AbstractBot.ts @@ -906,11 +906,11 @@ abstract class AbstractBot { async getWalletBalance(tokenDetails: any, provider: any, envType = "subnet") { let balance; - if (this.isNative(tokenDetails.symbol, envType)) { + if (this.isNative(tokenDetails.subnet_symbol, envType)) { balance = await provider.getBalance(this.account); } else { if (envType === "mainnet") { - balance = await this.contracts[tokenDetails.symbol].deployedContract.balanceOf(this.account); + balance = await this.contracts[tokenDetails.subnet_symbol].deployedContract.balanceOf(this.account); } else { balance = BigNumberEthers.from(0); }