diff --git a/data/ids.json b/data/ids.json index a39139d..5665826 100644 --- a/data/ids.json +++ b/data/ids.json @@ -1,6 +1,6 @@ { "cluster_urls": { - "devnet": "https://mango.devnet.rpcpool.com", + "devnet": "https://api.devnet.solana.com", "localnet": "http://127.0.0.1:8899", "mainnet-beta": "https://solana-api.projectserum.com", "testnet": "https://testnet.solana.com" @@ -9,7 +9,7 @@ { "cluster": "devnet", "name": "devnet.1", - "publicKey": "D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM", + "publicKey": "4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4", "quoteSymbol": "USDC", "mangoProgramId": "5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E", "serumProgramId": "DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY", @@ -18,106 +18,79 @@ "symbol": "USDC", "mintKey": "8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN", "decimals": 6, - "rootKey": "J2PZBR4M8V4LXDG8oPC8BG1t8JUSXHC6fSMCxR9tFdfZ", + "rootKey": "8HomaswMsbUtfdYeFd6zKBFfdzWZ8KqW7beu3wpJi6zE", "nodeKeys": [ - "9iXA2Y3UPqJJE6qe7TtRcxGdqYcToKh8sCZv88Jt4dXS" + "F7hQduZSp8jvFKH1LAkYByDhzKoJFeKTGqz2JzeT1fby" ] }, { "symbol": "MNGO", "mintKey": "Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC", "decimals": 6, - "rootKey": "1UBCGeMVmoNHt7Ldj7L6aj29f8oxRhuvCGwjJnTW1yU", + "rootKey": "scfyRHbzBnEyeELkVq8LP3QyNKZfzdF8AESmPqtqqc7", "nodeKeys": [ - "G9zKrvZhCgkAU6QUW37NjghKMBnmBdDzk3aYgbE6ZkJY" + "8A5QQKXGHnMUsPiBQN4dJeVDnJjjHQTeExUpqsBaRFVv" ] }, { "symbol": "BTC", "mintKey": "3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU", "decimals": 6, - "rootKey": "YyuJod2J35HhUYPq1gkregZjaD3Zr2m3MdZaUrmh74W", + "rootKey": "5peczazimSQpLiqpo9JeZeZJAhr6BvDxTkKLrQHQqW6u", "nodeKeys": [ - "CKjPnjQdHPDJDFKAevSCpLJ8NQk7UrsbCgbXQAh1AXgu" + "6AYdrMRPRdhWVGHaw9qVXcvbXAPn3xNH73bTvbG48c5L" ] }, { "symbol": "ETH", "mintKey": "Cu84KB3tDL6SbFgToHMLYVDJJXdJjenNzSKikeAvzmkA", "decimals": 6, - "rootKey": "Anjg6i35hDE3VTCRXcSTYaUMctMc6Wx5TrpJkVF2g2Uc", + "rootKey": "AKQLYJXdqMUxRMGskbxSrCUFB9hV2PXy7CgcwdCEiKKb", "nodeKeys": [ - "6kHBxELNpRhQ1D7DdNtZUZHeqV72kDPjhJb9Mqkpm8h" + "5iNkcp9cHuebGuvg7hkND19LDYEm5rz5hg73MyaCWgiZ" ] }, { "symbol": "SOL", "mintKey": "So11111111111111111111111111111111111111112", "decimals": 9, - "rootKey": "TSA9ikdc4fHJEGbkEEcGeXk4Snk3REd91Vvk67PCB8U", + "rootKey": "2i1USFkMnUrLGyF6HDWYw5VtPfDjpfL6bhjSyiCRMFS7", "nodeKeys": [ - "5XYKTZgoWfLQK8zmngNefLi6zE5J3LiUXZrfyfVRpy67" + "DzTqkCiD9Lb3e8tX5ozFzjwUmaHN8nfNGqLmYg1MHxvA" ] }, { "symbol": "SRM", "mintKey": "AvtB6w9xboLwA145E221vhof5TddhqsChYcx7Fy3xVMH", "decimals": 6, - "rootKey": "A3swcrvcnVTa1kaamjfxikxJrTRe3PVjAKb4ke3MqU2L", + "rootKey": "BodzTbB412CwnkJbDG6rQpvAy9MHPgqskpH4r7qn3nB7", "nodeKeys": [ - "EoL6ZSxXKKVPZyNYMSqF44JMxUFK7w4bwqXXb95i8sMZ" + "H9hkW2DtyrETf7EGmeiz9QdChf9thk5FFRb4HAXfC5An" ] }, { "symbol": "RAY", "mintKey": "3YFQ7UYJ7sNGpXTKBxM3bYLVxKpzVudXAe4gLExh5b3n", "decimals": 6, - "rootKey": "BGjFGQsocyTHQ87q8Sm6veM2fvrswbS9swfPwv1VPu4w", + "rootKey": "6NUEWYb2v4zc2dxeWPfswGZDLzjqaYzHG8bThctHG7jz", "nodeKeys": [ - "HbAproJH9NDXS4BNHtfeqvQQ6M7QCwvkHs79PCAJ62pb" - ] - }, - { - "symbol": "DOGE", - "mintKey": "6yr1xJP6Nfu8Bxp4L8WJQrtLqBGZrQm5n41PFm4ZmEyk", - "decimals": 6, - "rootKey": "H4pPY9sFtDe3mXJeNiPjx1dkqU2paUFDVhMZmHVwgL1w", - "nodeKeys": [ - "DGuaMXYY9VPWCUgaj5A2iopDE67mJrv66yPQJQemDpJd" - ] - }, - { - "symbol": "SUSHI", - "mintKey": "Edi5KNs2LnonULNmoTQqSymJ7VuMC9amTjLN5RJ1YMcq", - "decimals": 6, - "rootKey": "3SEr6tzAjq5PxydhhRDkXBnfAyHqdypVGH78hmyZMTjH", - "nodeKeys": [ - "GndC5WQVGpDfPoQV94krJq9TXwVkBNgdw4TgA8HKcfiL" - ] - }, - { - "symbol": "FTT", - "mintKey": "Fxh4bpZnRCnpg2vcH11ttmSTDSEeC5qWbPRZNZWnRnqY", - "decimals": 6, - "rootKey": "384x8UXptKQMcc4vcUT1xJJ3t8iwaHSed6Hux2E6FJ9G", - "nodeKeys": [ - "DRg3uVuyLZgf3aYQcQnsEL9ADpMJipoppRcqineGRK5t" + "DBAAoG5d21YouJinh5vgk9VBowPWfzXNbhBsPW2XisEb" ] }, { "symbol": "USDT", "mintKey": "DAwBSXe6w9g37wdE2tCrFbho3QHKZi4PjuBytQCULap2", "decimals": 6, - "rootKey": "HyncqkGfvmDf8CCXXTSYcPGJk9MfkoW7mm4hfHZ6EEZk", + "rootKey": "4Z1Yq3PotHzgdxhvj5q3tmhAWrbRZZpNtKGpjyAdJugD", "nodeKeys": [ - "91fZLKyYCXxxrfVrCogY1MJdqe9RBUQPvdWwncedMD9u" + "D6weykQ7DSzHKZQpFW59Z8gRduRFJAxxoM3p5Zn2N7FG" ] } ], "oracles": [ { "symbol": "MNGO", - "publicKey": "9qNwk4nFs2FzqqBNcbEfQwzYEGALsuuZz7qqV4UTyyrN" + "publicKey": "2s7XrK1c7tmT4GNuSzzPcTBHFWLKmNZh8vi3UUYCWyqL" }, { "symbol": "BTC", @@ -137,19 +110,7 @@ }, { "symbol": "RAY", - "publicKey": "DySvRB195HvXbPCz4VU1KS7q2DrpAMoKAPDWRsMRzx4k" - }, - { - "symbol": "DOGE", - "publicKey": "4L6YhY8VvUgmqG5MvJkUJATtzB2rFqdrJwQCmFLv4Jzy" - }, - { - "symbol": "SUSHI", - "publicKey": "AmALh5D5d27r3kBsTctwCcK9oV2bYy168y7DjgT8vTnc" - }, - { - "symbol": "FTT", - "publicKey": "6vivTRs5ZPeeXbjo7dfburfaYDWoXjBtdtuYgQRuGfu" + "publicKey": "8jLbp5tcdWpqATwuFwwQ5eBPWsDxaFopJqnXhxmD6caN" }, { "symbol": "USDT", @@ -159,225 +120,159 @@ "perpMarkets": [ { "name": "MNGO-PERP", - "publicKey": "Eb9kbaZN5im9RiyJJi9j231vdGjwHqk9U87BTH8vozHn", + "publicKey": "GB4QffZnSGVmCh2qscTxGVwkqBSt7NB8B5fpuRcDFCFD", "baseSymbol": "MNGO", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 0, - "bidsKey": "8DioiDW4L9UWf2kfKFY1kcsLMcVWESavAfct8z6JBGaY", - "asksKey": "4Bk1VDtXDtKQAxS31kpdJmVs5AXUd3DaGt1PEgtW26cR", - "eventsKey": "HfACePStB6PcrAGA6YKBPscXEm7kDhLwML98xmcQ55gW" + "bidsKey": "9a3FU66bknYPSPAFG5Wmv3hFCoJ2VMpdrefZUPdGJyMJ", + "asksKey": "5cx3XqHQU8vY5qPrbEccqTvuzXdgEwcbCbHDSD9fVoGE", + "eventsKey": "BiJ6kg2ncPt3HPJctM1bYoBWHXzvwWhD7AB883tiNWzr" }, { "name": "BTC-PERP", - "publicKey": "5FePG6TGQ2PybQVmFvKbCEXEYKmohoCUmz91zzVCqrTU", + "publicKey": "CekAcHL8x6XjMXYNCfTFrs4rAAYkNCdir2LCdjJHdmCB", "baseSymbol": "BTC", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 1, - "bidsKey": "GE9szLB8GvtqDH5QN9CuovzKDdSXuY1oGHQGwKyk4hTT", - "asksKey": "BxJEW9AewNwBf8RSn7LLjpGmueKrSL5QX8WhDXwTaeb2", - "eventsKey": "CxCVE8pNJUihmaGzK2eLSb9XZ2XQR4r2xpJk7brZj4kX" + "bidsKey": "8Mx11pN2Vj9bRH3DHqu9XdFp7My7VYjM3FL1TyY9tZ6z", + "asksKey": "fJ8goLHFpdtbSY6uaKVRGP2WH21csAip7B8QRagVwjt", + "eventsKey": "HNxDQsf8ntqmZy6YDuWrWQieuYjLTaucq652tpf6jFXN" }, { "name": "ETH-PERP", - "publicKey": "9GHN7VGxNSCaSiDtTeZkT4ZseqVVkCTKw7VYEAaJqiNc", + "publicKey": "1h3QZQjo4X4bnJAPignsgfEebaJvhAyYJ22n5Asj2Aq", "baseSymbol": "ETH", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 2, - "bidsKey": "9bPCjgu17vtaSMe4ojWCEBumd1KmttweUPHVnfakaodt", - "asksKey": "8VhKgHYdeVTFvPrn1zeA6iHfvAtFXQnSKDLsk38YhZ8n", - "eventsKey": "FPgTy3JmLKck9jyQzBFAmRGq8G4WmifeXq6CJJMivGtb" + "bidsKey": "BQy6FyJZ5Nn8pfScyLmmxmzpWjJEdyx7Wgxd8Amx2sE6", + "asksKey": "J3Buki4SKYZUZZq2KhouEaPQi9C7CyNCJn7SFaRCTn1V", + "eventsKey": "EYkinFh4MvyknVWc8VSr5ofqoW7RN2WccYWRsPB9LFKH" }, { "name": "SOL-PERP", - "publicKey": "Htds23imNxeeR778DLXHXDjUnr2sFYdtj31tz6hwSZnV", + "publicKey": "8bdzbDmK776L7SYo15jFrCE1jZpGJ5Hvi3HCX4nkG2SC", "baseSymbol": "SOL", "baseDecimals": 9, "quoteDecimals": 6, "marketIndex": 3, - "bidsKey": "8fD5gMavPbRMJd4KMFopLF6fzhKMQZHwH5wMZMxLkMJe", - "asksKey": "3AdnHLkNw9qm4vwRsjgs9KffkCSZr5JvGLEgFx6QBJaM", - "eventsKey": "7nMo3Apws96PqEP4ejnoJTQimc9DRsz91NV32wHasQEZ" + "bidsKey": "36j8vFEy8MFSEZ1qbgNBZ85bfLir3m2JWK1Xyfod3SXq", + "asksKey": "6gfw77TVq2dasBGrbNQNfUEjj1qH8yfTZxQdsqm1czGB", + "eventsKey": "CKh8QDgvGrVY1anhL6uWcTqSTkPkZqMs2ijvYJcVd4N4" }, { "name": "SRM-PERP", - "publicKey": "8j8JEHSduFv8L8tw4AybTTRzELKQbu2xnjcTUdxZ8SZ2", + "publicKey": "H1zA6828E6pitokeK7bjo9bNGmcQnUAEzNDVymnjgnSo", "baseSymbol": "SRM", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 4, - "bidsKey": "ExRkH8dUbeTADeffrpV8kFw3P12s5Ya8K4fvQ4iUgru7", - "asksKey": "6AiXmTA9c1eG7vmDuckNUTM3qdV9KpCsi2UvVTSYWA9r", - "eventsKey": "6bhy7yUzZoPKMK4TdsnhDMs9CMRQQ8iqynkWqir9VTqg" + "bidsKey": "674JmaAdzSfUJ163tq1mL53zPrAU3xEn67n4oCBJwQ1U", + "asksKey": "6oRDC75LQkQRwPbMftfdQLazp62hUHGDnuky9T5BZoU4", + "eventsKey": "2sFGWmFEie8A123mXHf1C6rYbKhNEfcjbNThYDPQbVQ4" }, { "name": "RAY-PERP", - "publicKey": "JCVKRwUG81Wpo3ErTCfWWZsuvRxECEtGRkLppRceef7X", + "publicKey": "9rt89vb7o2uEUUhM435YXCBE9nYzdxYqWfgbumDX5qDd", "baseSymbol": "RAY", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 5, - "bidsKey": "9M19Sk7ydE5omHBN5W2EF7idqtcPGMTPmwN4s2TY4BSS", - "asksKey": "BpdPV6Q6zGeGb2jzr16RrMBNLSANxjxX8VuFr2sEwY1H", - "eventsKey": "G9GJ7ykDo165PwLFMdKYiXDsnmfzPGji6764Q9rU2VdD" - }, - { - "name": "DOGE-PERP", - "publicKey": "BTxGBYaS64UVtsPkiweMRKuKBLiy7Du23t52HHQNjtau", - "baseSymbol": "DOGE", - "baseDecimals": 6, - "quoteDecimals": 6, - "marketIndex": 6, - "bidsKey": "FvGjyWeWGwtmwoPH11BLWiDA2kqCmrw564QvpxoFCxFG", - "asksKey": "BWaGbAoTAgBLyp7ZcCtA4FfadqvNqELYEhdp5R5eQaYi", - "eventsKey": "F2ydUUxqGiVjQXQwqx6qW6NPJrtsefSsnqkEeCMhA1Hs" - }, - { - "name": "SUSHI-PERP", - "publicKey": "A98F12sHfmJPbY5ZoVVkeuA7YEJTBczTtCzN33hP62dv", - "baseSymbol": "SUSHI", - "baseDecimals": 6, - "quoteDecimals": 6, - "marketIndex": 7, - "bidsKey": "G3JrEBtwJZT4NYEvvXbZFs3mRNf4EX7WKXY8REPhYTrv", - "asksKey": "5s3Ys2wwV6fTCiYKjzwsSUQx5A9SCY5RQpbBGbduX9fD", - "eventsKey": "B3ufGFeoW4JnNgrf5qBgQ2W7WgG3AnBDR6cfgRvh4gSY" - }, - { - "name": "FTT-PERP", - "publicKey": "AcUJeQ9yNdEjGUbGFm8jWWGcFPXX2MBwGuxyW573Ff1c", - "baseSymbol": "FTT", - "baseDecimals": 6, - "quoteDecimals": 6, - "marketIndex": 8, - "bidsKey": "DwZ3scyS33yvzrmmComF1cYPr62KpVgciBssyHhLJ7kw", - "asksKey": "GijPgMq9aydVGRWvfSwRVBVszmwssUHBwuSM35BuhqXN", - "eventsKey": "8X9i5vLZ8CkMWxbrsWikeorQzfMBtaMhfDMwYXTeiFNS" + "bidsKey": "6hRYk2JJibhFFShZFZPqussECXNxCvi2oC38V2GwETPN", + "asksKey": "GBoPouNmbdmmpLCdEDzXhyoRfdQYofK7xD3vY8oZckRG", + "eventsKey": "8Dy78QoWXufCwQNSLRKJ9bH1JcUho3GfRvbDqiyALQC7" }, { "name": "USDT-PERP", - "publicKey": "Djr75WctR92VCqssZ619qPJbKKZFjEMwi86mFdN4VfFi", + "publicKey": "HzA2xewTzqboVJk8yeSP9wqpSE4XHEmGMzsiFBmwCszE", "baseSymbol": "USDT", "baseDecimals": 6, "quoteDecimals": 6, - "marketIndex": 9, - "bidsKey": "8iJ7oHisRHsxAygGfp1ki9GZh8k2QwEirF6uUbr98XM3", - "asksKey": "bhJxk5Zc6SxbBbj6kEauYGvZaxzSCkYcWtwmQwMjfP3", - "eventsKey": "GAayxsWfK7XVg3UXb79XS3CtuJSwFuzeLtEHvSfDSuoS" + "marketIndex": 6, + "bidsKey": "93n4jwHsbCEvZZ4cydyy7c8AHWY4LtPSdP6CLLjzJSw", + "asksKey": "BP2rC9v87xov554hcMVwRW5qB1qcRa27RXKTbA6YobwK", + "eventsKey": "GRUrFv3M5L5cPhMETkSTBssZZT2B9DdDwoeW2BQ3Jv1y" } ], "spotMarkets": [ { "name": "MNGO/USDC", - "publicKey": "BP5duanM1mEVyW6hi1fXz5KZmW15DpJuL3yR8V1bH3Py", + "publicKey": "D9KWifyaFX8qxyktRzzCLv4n37ameEoUP1jPkMdu13JZ", "baseSymbol": "MNGO", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 0, - "bidsKey": "BBaYoN6utgyKMDNhKPqvREMNKbqj4sE7PPCr9cmFv7c8", - "asksKey": "6nRnAvEPQ6ycVRTzpp7s97BFfzDF7Niio5MoZ7Nowip9", - "eventsKey": "5EwoR3usrHeMPn9tFfXnpvibgmqB6QyMaNfk9jaZUtkZ" + "bidsKey": "BEJD7DrCxv1GigvcXRZLsq8gr13h7ypwSNDYUTxAqjzj", + "asksKey": "AkXKeB1bpvieCGDKgcSDs1cvKDVvqemynq7Xpbvp23ic", + "eventsKey": "5gnYPsN26T4hGDZYmuddG9aeRXZUpPGDNjn5a9vXThdj" }, { "name": "BTC/USDC", - "publicKey": "6LUe1qbDwoj3dmM4jvXwshRAcpMFH7xQ5dWyssAtAuHV", + "publicKey": "BYXAPyT9fKiyUJ162mqXbVmchQaEwMnrcenM9esDV4k5", "baseSymbol": "BTC", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 1, - "bidsKey": "8SCQybswfLSVQSZaDjACcj7kVBzG1nPhMxB4M4WmsGKp", - "asksKey": "D6wzhFJW6QZDotBuFWmy6e9rszQm9W5FR32Z8KtMGUbf", - "eventsKey": "G4UuuNB92mquXqDJirV35ooWmHGqoD57zzG6FAbufCUu" + "bidsKey": "5wkoQDMYcrfuKB9Die5yLZTboWHcmW1M6yJXM5uhk66Z", + "asksKey": "DBS7Zw5zFC58jVsqX8bRwSjtTc8ca5r27g6Y4ikr9hhv", + "eventsKey": "4hrYeHTGRGcEWkqLZqVwuMAmo1dtankVNML2psBBhkmT" }, { "name": "ETH/USDC", - "publicKey": "6YzKiCwaURhEVEXxLBD8gNQXziCPqi6h17dhpH17NNFD", + "publicKey": "G7NYXEQ6W4mVoMinn9a8XaY4oswhW59NhtNWDQg5An2U", "baseSymbol": "ETH", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 2, - "bidsKey": "DYELab7pC4v78Q6n8YXEAzZqLJdVPXbHDuSQDX1z5kJV", - "asksKey": "dWD2Kc3SbEDKvCtPxfeuBXLbk1o2NFhN47AG65gwwcz", - "eventsKey": "Aen28QFiv6MaQDcbq58fz4Krttj5HXxvfpUr5js2sXoW" + "bidsKey": "2RRd7yVxEhQzBBuNHBkR49SxWcQ8tSKv2D61DQo4DZVx", + "asksKey": "69WSZeZ7KTky19XH1Z9g2ZMkZJEt8pweD2WZcw9heRNb", + "eventsKey": "Huy7jJX5fyuHtyWEN2xjjcSmEB18riqTFDCwUMsTtGm" }, { "name": "SOL/USDC", - "publicKey": "7GLPw3pdjpyf2YpXoXo1PTDa5WciT8NDNzz3PnMB1ZTM", + "publicKey": "6pV5PfVL6Ct5jiiySyt144ocMcuepLdAuF3umYMuh3rN", "baseSymbol": "SOL", "baseDecimals": 9, "quoteDecimals": 6, "marketIndex": 3, - "bidsKey": "6DoTW6uKSJhfsK8CzLM9CWfTn4QjzF3gksPyLgcnZgys", - "asksKey": "4in1zY5zr7S7Rfg9txKzd7cgnHfNriQQH4LiwTd2MhGn", - "eventsKey": "DDp6dFXwZxyzg65q5sfe58NCpps5nFuha5xS8Kb1EDgU" + "bidsKey": "5N2KmqcnXSP2PE2Dg9UF2f1Y2kF7sdi8xTnzAwhqF8iv", + "asksKey": "7U1XLt3mbQVYdNR7JoKoJyN8TfQUA6Lv5VDZaAKz3waa", + "eventsKey": "34B9UoVjhUn7BXyXkfFHpQNWBZeGWhg9rJEBLgyocqiF" }, { "name": "SRM/USDC", - "publicKey": "FM3NeE8ZhzcZXf2FtLGiSHTbLzQsemHh3emmBMLyFMDu", + "publicKey": "76JPTPeZr6UWzU4jcjLfGKAHfSywsXiwrgGo7dt7Kwzb", "baseSymbol": "SRM", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 4, - "bidsKey": "8aeTnuRxPuMZT6EjBxSuPiaKPVHah5gznq3mNszkDPkZ", - "asksKey": "6eAGyCQg8vUNvBV96ztoArAKTudBGsr8XSaQbWWcvuXj", - "eventsKey": "UgAd1bmJ3zr5MAUz8XpT5ku32HK73W8jCjyUwSvgQZM" + "bidsKey": "Dc4xX9VSV3R71jDKiMSPZqpa8EBhVo1GHZxkCMfVepkx", + "asksKey": "5bvsugaaA7c53eNdiVzuTG68pTPR4QGNK7CEYyC3PbML", + "eventsKey": "VvhudujDXLXCkwcDJXrMbtSBgMHdEjJrLys14fy6SQ9" }, { "name": "RAY/USDC", - "publicKey": "G8W9b1ACTKipefeCD8wrBTFygqCY48fX22hywFwE9ne8", + "publicKey": "CwBV7qFPkfRrJPao8jaoAK5NoWYVYSVgtaBvAXN7JZs7", "baseSymbol": "RAY", "baseDecimals": 6, "quoteDecimals": 6, "marketIndex": 5, - "bidsKey": "8HQaw8X8ph2mqpFhGrD1FZC1VDfBkyw5gtTg6jkjCZPd", - "asksKey": "77XVr3Ypgs8SNCem5N8wi97GQTGyrs16jEWw6nS1Bdsn", - "eventsKey": "4XcMk15DBK1cBsvKXRMo8m1AWZbnNpWjPBwKrhCLnVhN" - }, - { - "name": "DOGE/USDC", - "publicKey": "147v2QNqhykdshNTzBU9SqMZ1MB8zfum8VusL3mTHRpi", - "baseSymbol": "DOGE", - "baseDecimals": 6, - "quoteDecimals": 6, - "marketIndex": 6, - "bidsKey": "E2jYUnxNW7atftcMEEeC64JV7WQuiK5K5zvWVVaZAXTu", - "asksKey": "5RDn6fXNWVoAvJDvvc6sH1nBdqPavKmqRUF1394rNmm4", - "eventsKey": "5byXwPysnJqjkuaMNhYxBXLLA4CQkXqmRbFTvDDSe7fs" - }, - { - "name": "SUSHI/USDC", - "publicKey": "52x7jVwSLzjBuur38HSpQJUsNTUnMtbawYuNwMFf5gno", - "baseSymbol": "SUSHI", - "baseDecimals": 6, - "quoteDecimals": 6, - "marketIndex": 7, - "bidsKey": "AhQ9ibX2gKpqyXiRCFLn31NnNJ2D7Ye4wpMKdW2HU5wm", - "asksKey": "ET8PeUBxiLbT5FRuxG7gSgzomakK1aGpdEvB7z7GgnPy", - "eventsKey": "5QcSUUMxKMJQwe8jELZMJYAdSXYTNoLTWsKD8vPiLXP3" - }, - { - "name": "FTT/USDC", - "publicKey": "AqqoYLbCM3Kx575mYaEKQjvmJytC3JhYidjdDJybSobR", - "baseSymbol": "FTT", - "baseDecimals": 6, - "quoteDecimals": 6, - "marketIndex": 8, - "bidsKey": "AQP35WTu3e3Ci7wGwupt1tqLme8yJpMKMCVqRUFgLuSk", - "asksKey": "BSVn6uTnb4jCbG8CxQstaXdT6T3nBKHCk7K9dr9RHb38", - "eventsKey": "9NF9f5iDBzJcpFuqcTv2jdENvRad4HGPyzphhJPBU48k" + "bidsKey": "H18vDMumfWDxgU6YVJb1D8fhahvkSUubzA7jU61q8RiP", + "asksKey": "7D4TYmMVi8HpKu8Tg2CHV998HQe2iZj25B295MDdabdU", + "eventsKey": "CGchuvhJjfMXy5Rh272eM6z8y7k6v8XH4UYJZSMUTjUP" }, { "name": "USDT/USDC", - "publicKey": "2jnUTkxsDvRmiZzWw1wpxuTnT1SbT6PmYFKNPbWdyY6U", + "publicKey": "97N64HezGkNs1sPBUMUxLLxkeCoBqSNzZmipxpeBcYUg", "baseSymbol": "USDT", "baseDecimals": 6, "quoteDecimals": 6, - "marketIndex": 9, - "bidsKey": "C1gxQ8NjqnaFs9TC5U7de5YKfAyNpQTiYWQAjPHMDE91", - "asksKey": "AhnGqCuTNzLiQ6Y4m2oxds2sog3u2ChX8MXCMYyaPCb4", - "eventsKey": "GBEkcp2qqu13qxtYFXJxER1W1bAww2yBj9tCmR9ZXUde" + "marketIndex": 6, + "bidsKey": "BoKZMtnEgzV1gtix6RotBq4wteNXteGFEyeTMC88BUyw", + "asksKey": "EbgYUYhPTqFxMqc7pq2v9MWTbzu2m5frzvw6ePTsAFWq", + "eventsKey": "38X8AuewBYZATEovYnXr7znDbiAxkxxEn7RYjXDtVn1T" } ] }, diff --git a/docs/MarketMaking.md b/docs/MarketMaking.md index 286ef64..7194412 100644 --- a/docs/MarketMaking.md +++ b/docs/MarketMaking.md @@ -156,7 +156,7 @@ def pulse(self, context: mango.Context, model_state: ModelState): cancellations = mango.CombinableInstructions.empty() for to_cancel in reconciled.to_cancel: self.logger.info(f"Cancelling {self.market.symbol} {to_cancel}") - cancel = self.market_instruction_builder.build_cancel_order_instructions(to_cancel) + cancel = self.market_instruction_builder.build_cancel_order_instructions(to_cancel, ok_if_missing=True) cancellations += cancel place_orders = mango.CombinableInstructions.empty() diff --git a/mango/account.py b/mango/account.py index ebe705e..dd721c2 100644 --- a/mango/account.py +++ b/mango/account.py @@ -13,6 +13,8 @@ # [Github](https://github.com/blockworks-foundation) # [Email](mailto:hello@blockworks.foundation) +from mango.perpopenorders import PerpOpenOrders +from mango.placedorder import PlacedOrder from mango.tokeninfo import TokenInfo import typing @@ -27,6 +29,7 @@ from .encoding import encode_key from .group import Group from .layouts import layouts from .metadata import Metadata +from .orders import Side from .perpaccount import PerpAccount from .token import Token from .tokenvalue import TokenValue @@ -125,13 +128,24 @@ class Account(AddressableAccount): in_margin_basket: typing.Sequence[bool] = list([bool(in_basket) for in_basket in layout.in_margin_basket]) active_in_basket: typing.List[bool] = [] basket: typing.List[AccountBasketBaseToken] = [] + placed_orders_all_markets: typing.List[typing.List[PlacedOrder]] = [[] for _ in range(len(group.tokens) - 1)] + for index, order_market in enumerate(layout.order_market): + if order_market != 0xFF: + side = Side.from_value(layout.order_side[index]) + id = layout.order_ids[index] + client_id = layout.client_order_ids[index] + placed_order = PlacedOrder(id, client_id, side) + placed_orders_all_markets[int(order_market)] += [placed_order] + for index, token_info in enumerate(group.tokens[:-1]): if token_info: intrinsic_deposit = token_info.root_bank.deposit_index * layout.deposits[index] deposit = TokenValue(token_info.token, token_info.token.shift_to_decimals(intrinsic_deposit)) intrinsic_borrow = token_info.root_bank.borrow_index * layout.borrows[index] borrow = TokenValue(token_info.token, token_info.token.shift_to_decimals(intrinsic_borrow)) - perp_account = PerpAccount.from_layout(layout.perp_accounts[index], mngo_token_info.token) + perp_open_orders = PerpOpenOrders(placed_orders_all_markets[index]) + perp_account = PerpAccount.from_layout( + layout.perp_accounts[index], perp_open_orders, mngo_token_info.token) spot_open_orders = layout.spot_open_orders[index] basket_item: AccountBasketBaseToken = AccountBasketBaseToken( token_info, deposit, borrow, spot_open_orders, perp_account) diff --git a/mango/instructions.py b/mango/instructions.py index 6b11a0c..110a91d 100644 --- a/mango/instructions.py +++ b/mango/instructions.py @@ -319,20 +319,19 @@ def build_compound_serum_place_order_instructions(context: Context, wallet: Wall # -def build_cancel_perp_order_instructions(context: Context, wallet: Wallet, account: Account, perp_market_details: PerpMarketDetails, order: Order) -> CombinableInstructions: +def build_cancel_perp_order_instructions(context: Context, wallet: Wallet, account: Account, perp_market_details: PerpMarketDetails, order: Order, invalid_id_ok: bool) -> CombinableInstructions: # Prefer cancelling by client ID so we don't have to keep track of the order side. if order.client_id != 0: data: bytes = layouts.CANCEL_PERP_ORDER_BY_CLIENT_ID.build( { - "client_order_id": order.client_id + "client_order_id": order.client_id, + "invalid_id_ok": invalid_id_ok }) else: - # { buy: 0, sell: 1 } - raw_side: int = 1 if order.side == Side.SELL else 0 data = layouts.CANCEL_PERP_ORDER.build( { "order_id": order.id, - "side": raw_side + "invalid_id_ok": invalid_id_ok }) # Accounts expected by this instruction (both CANCEL_PERP_ORDER and CANCEL_PERP_ORDER_BY_CLIENT_ID are the same): @@ -648,8 +647,15 @@ def build_spot_place_order_instructions(context: Context, wallet: Wallet, group: base_token_info = base_token_infos[0] quote_token_info = group.shared_quote_token - root_bank: RootBank = quote_token_info.root_bank if side == Side.BUY else base_token_info.root_bank - node_bank: NodeBank = root_bank.pick_node_bank(context) + base_root_bank: RootBank = base_token_info.root_bank + base_node_bank: NodeBank = base_root_bank.pick_node_bank(context) + quote_root_bank: RootBank = quote_token_info.root_bank + quote_node_bank: NodeBank = quote_root_bank.pick_node_bank(context) + + vault_signer = PublicKey.create_program_address( + [bytes(market.state.public_key()), market.state.vault_signer_nonce().to_bytes(8, byteorder="little")], + market.state.program_id(), + ) fee_discount_address_meta: typing.List[AccountMeta] = [] if fee_discount_address is not None: @@ -668,13 +674,18 @@ def build_spot_place_order_instructions(context: Context, wallet: Wallet, group: AccountMeta(is_signer=False, is_writable=True, pubkey=market.state.event_queue()), AccountMeta(is_signer=False, is_writable=True, pubkey=market.state.base_vault()), AccountMeta(is_signer=False, is_writable=True, pubkey=market.state.quote_vault()), - AccountMeta(is_signer=False, is_writable=False, pubkey=root_bank.address), - AccountMeta(is_signer=False, is_writable=True, pubkey=node_bank.address), - AccountMeta(is_signer=False, is_writable=True, pubkey=node_bank.vault), + AccountMeta(is_signer=False, is_writable=False, pubkey=base_root_bank.address), + AccountMeta(is_signer=False, is_writable=True, pubkey=base_node_bank.address), + AccountMeta(is_signer=False, is_writable=True, pubkey=base_node_bank.vault), + AccountMeta(is_signer=False, is_writable=False, pubkey=quote_root_bank.address), + AccountMeta(is_signer=False, is_writable=True, pubkey=quote_node_bank.address), + AccountMeta(is_signer=False, is_writable=True, pubkey=quote_node_bank.vault), AccountMeta(is_signer=False, is_writable=False, pubkey=TOKEN_PROGRAM_ID), AccountMeta(is_signer=False, is_writable=False, pubkey=group.signer_key), AccountMeta(is_signer=False, is_writable=False, pubkey=SYSVAR_RENT_PUBKEY), - AccountMeta(is_signer=False, is_writable=False, pubkey=group.srm_vault or SYSTEM_PROGRAM_ADDRESS), + AccountMeta(is_signer=False, is_writable=False, pubkey=vault_signer), + AccountMeta(is_signer=False, is_writable=False, + pubkey=group.msrm_vault or group.srm_vault or SYSTEM_PROGRAM_ADDRESS), *list([AccountMeta(is_signer=False, is_writable=(oo_address == open_orders_address), pubkey=oo_address or SYSTEM_PROGRAM_ADDRESS) for oo_address in account.spot_open_orders]), *fee_discount_address_meta diff --git a/mango/layouts/layouts.py b/mango/layouts/layouts.py index 6f8442e..f1b711f 100644 --- a/mango/layouts/layouts.py +++ b/mango/layouts/layouts.py @@ -326,6 +326,7 @@ MAX_NODE_BANKS: int = 8 QUOTE_INDEX: int = MAX_TOKENS - 1 MAX_BOOK_NODES: int = 1024 MAX_ORDERS: int = 32 +MAX_PERP_OPEN_ORDERS: int = 64 DATA_TYPE = construct.Enum(construct.Int8ul, Group=0, Account=1, RootBank=2, NodeBank=3, PerpMarket=4, Bids=5, Asks=6, Cache=7, EventQueue=8) @@ -541,30 +542,6 @@ NODE_BANK = construct.Struct( "vault" / PublicKeyAdapter() ) -# # πŸ₯­ PERP_OPEN_ORDERS -# -# Here's the [Rust structure](https://github.com/blockworks-foundation/mango-v3/blob/main/program/src/state.rs): -# ``` -# #[derive(Copy, Clone, Pod)] -# #[repr(C)] -# pub struct PerpOpenOrders { -# pub bids_quantity: i64, // total contracts in sell orders -# pub asks_quantity: i64, // total quote currency in buy orders -# pub is_free_bits: u32, -# pub is_bid_bits: u32, -# pub orders: [i128; 32], -# pub client_order_ids: [u64; 32], -# } -# ``` -PERP_OPEN_ORDERS = construct.Struct( - "bids_quantity" / SignedDecimalAdapter(), - "asks_quantity" / SignedDecimalAdapter(), - "free_slot_bits" / DecimalAdapter(4), - "is_bid_bits" / DecimalAdapter(4), - "orders" / construct.Array(MAX_ORDERS, SignedDecimalAdapter(16)), - "client_order_ids" / construct.Array(MAX_ORDERS, DecimalAdapter()) -) - # # πŸ₯­ PERP_ACCOUNT # # Here's the [Rust structure](https://github.com/blockworks-foundation/mango-v3/blob/main/program/src/state.rs): @@ -577,16 +554,31 @@ PERP_OPEN_ORDERS = construct.Struct( # # pub long_settled_funding: I80F48, # pub short_settled_funding: I80F48, -# pub open_orders: PerpOpenOrders, -# pub liquidity_points: I80F48, +# +# // *** orders related info +# pub bids_quantity: i64, // total contracts in sell orders +# pub asks_quantity: i64, // total quote currency in buy orders +# +# /// Amount that's on EventQueue waiting to be processed +# pub taker_base: i64, +# pub taker_quote: i64, +# +# pub mngo_accrued: u64, # } # ``` PERP_ACCOUNT = construct.Struct( "base_position" / SignedDecimalAdapter(), "quote_position" / FloatI80F48Adapter(), + "long_settled_funding" / FloatI80F48Adapter(), "short_settled_funding" / FloatI80F48Adapter(), - "open_orders" / PERP_OPEN_ORDERS, + + "bids_quantity" / SignedDecimalAdapter(), + "asks_quantity" / SignedDecimalAdapter(), + + "taker_base" / SignedDecimalAdapter(), + "taker_quote" / SignedDecimalAdapter(), + "mngo_accrued" / DecimalAdapter(), ) @@ -596,6 +588,7 @@ PERP_ACCOUNT = construct.Struct( # ``` # pub const INFO_LEN: usize = 32; # pub const MAX_NUM_IN_MARGIN_BASKET: u8 = 10; +# pub const MAX_PERP_OPEN_ORDERS: usize = 64; # #[derive(Copy, Clone, Pod, Loadable)] # #[repr(C)] # pub struct MangoAccount { @@ -615,7 +608,13 @@ PERP_ACCOUNT = construct.Struct( # // Perps related data # pub perp_accounts: [PerpAccount; MAX_PAIRS], # +# pub order_market: [u8; MAX_PERP_OPEN_ORDERS], +# pub order_side: [Side; MAX_PERP_OPEN_ORDERS], +# pub orders: [i128; MAX_PERP_OPEN_ORDERS], +# pub client_order_ids: [u64; MAX_PERP_OPEN_ORDERS], +# # pub msrm_amount: u64, +# # /// This account cannot open new positions or borrow until `init_health >= 0` # pub being_liquidated: bool, # @@ -636,6 +635,10 @@ MANGO_ACCOUNT = construct.Struct( "borrows" / construct.Array(MAX_TOKENS, FloatI80F48Adapter()), "spot_open_orders" / construct.Array(MAX_PAIRS, PublicKeyAdapter()), "perp_accounts" / construct.Array(MAX_PAIRS, PERP_ACCOUNT), + "order_market" / construct.Array(MAX_PERP_OPEN_ORDERS, DecimalAdapter(1)), + "order_side" / construct.Array(MAX_PERP_OPEN_ORDERS, DecimalAdapter(1)), + "order_ids" / construct.Array(MAX_PERP_OPEN_ORDERS, SignedDecimalAdapter(16)), + "client_order_ids" / construct.Array(MAX_PERP_OPEN_ORDERS, DecimalAdapter()), "msrm_amount" / DecimalAdapter(), "being_liquidated" / DecimalAdapter(1), "is_bankrupt" / DecimalAdapter(1), @@ -1203,7 +1206,7 @@ CANCEL_PERP_ORDER = construct.Struct( "variant" / construct.Const(14, construct.BytesInteger(4, swapped=True)), "order_id" / DecimalAdapter(16), - "side" / DecimalAdapter(4) # { buy: 0, sell: 1 } + "invalid_id_ok" / construct.Flag ) @@ -1327,7 +1330,8 @@ CANCEL_SPOT_ORDER = construct.Struct( CANCEL_PERP_ORDER_BY_CLIENT_ID = construct.Struct( "variant" / construct.Const(13, construct.BytesInteger(4, swapped=True)), - "client_order_id" / DecimalAdapter() + "client_order_id" / DecimalAdapter(), + "invalid_id_ok" / construct.Flag ) # Run the Mango crank. diff --git a/mango/marketinstructionbuilder.py b/mango/marketinstructionbuilder.py index e4db7ae..6bb3be0 100644 --- a/mango/marketinstructionbuilder.py +++ b/mango/marketinstructionbuilder.py @@ -47,7 +47,7 @@ class MarketInstructionBuilder(metaclass=abc.ABCMeta): self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) @abc.abstractmethod - def build_cancel_order_instructions(self, order: Order) -> CombinableInstructions: + def build_cancel_order_instructions(self, order: Order, ok_if_missing: bool = False) -> CombinableInstructions: raise NotImplementedError( "MarketInstructionBuilder.build_cancel_order_instructions() is not implemented on the base type.") @@ -81,7 +81,7 @@ class NullMarketInstructionBuilder(MarketInstructionBuilder): super().__init__() self.symbol: str = symbol - def build_cancel_order_instructions(self, order: Order) -> CombinableInstructions: + def build_cancel_order_instructions(self, order: Order, ok_if_missing: bool = False) -> CombinableInstructions: return CombinableInstructions.empty() def build_place_order_instructions(self, order: Order) -> CombinableInstructions: diff --git a/mango/marketmaking/marketmaker.py b/mango/marketmaking/marketmaker.py index f196f9b..f0ace48 100644 --- a/mango/marketmaking/marketmaker.py +++ b/mango/marketmaking/marketmaker.py @@ -63,7 +63,7 @@ class MarketMaker: cancellations = mango.CombinableInstructions.empty() for to_cancel in reconciled.to_cancel: self.logger.info(f"Cancelling {self.market.symbol} {to_cancel}") - cancel = self.market_instruction_builder.build_cancel_order_instructions(to_cancel) + cancel = self.market_instruction_builder.build_cancel_order_instructions(to_cancel, ok_if_missing=True) cancellations += cancel place_orders = mango.CombinableInstructions.empty() diff --git a/mango/marketoperations.py b/mango/marketoperations.py index f270004..3e77036 100644 --- a/mango/marketoperations.py +++ b/mango/marketoperations.py @@ -55,7 +55,7 @@ class MarketOperations(metaclass=abc.ABCMeta): self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) @abc.abstractmethod - def cancel_order(self, order: Order) -> typing.Sequence[str]: + def cancel_order(self, order: Order, ok_if_missing: bool = False) -> typing.Sequence[str]: raise NotImplementedError("MarketOperations.cancel_order() is not implemented on the base type.") @abc.abstractmethod @@ -93,7 +93,7 @@ class NullMarketOperations(MarketOperations): super().__init__() self.market_name: str = market_name - def cancel_order(self, order: Order) -> typing.Sequence[str]: + def cancel_order(self, order: Order, ok_if_missing: bool = False) -> typing.Sequence[str]: self.logger.info(f"Cancelling order {order}.") return [""] diff --git a/mango/perpaccount.py b/mango/perpaccount.py index fc4d4b4..851d85e 100644 --- a/mango/perpaccount.py +++ b/mango/perpaccount.py @@ -28,29 +28,38 @@ from .tokenvalue import TokenValue # class PerpAccount: def __init__(self, base_position: Decimal, quote_position: Decimal, long_settled_funding: Decimal, - short_settled_funding: Decimal, mngo_accrued: TokenValue, open_orders: PerpOpenOrders): + short_settled_funding: Decimal, bids_quantity: Decimal, asks_quantity: Decimal, + taker_base: Decimal, taker_quote: Decimal, mngo_accrued: TokenValue, + open_orders: PerpOpenOrders): self.base_position: Decimal = base_position self.quote_position: Decimal = quote_position self.long_settled_funding: Decimal = long_settled_funding self.short_settled_funding: Decimal = short_settled_funding + self.bids_quantity: Decimal = bids_quantity + self.asks_quantity: Decimal = asks_quantity + self.taker_base: Decimal = taker_base + self.taker_quote: Decimal = taker_quote self.mngo_accrued: TokenValue = mngo_accrued self.open_orders: PerpOpenOrders = open_orders @staticmethod - def from_layout(layout: layouts.PERP_ACCOUNT, mngo_token: Token) -> "PerpAccount": + def from_layout(layout: layouts.PERP_ACCOUNT, open_orders: PerpOpenOrders, mngo_token: Token) -> "PerpAccount": base_position: Decimal = layout.base_position quote_position: Decimal = layout.quote_position long_settled_funding: Decimal = layout.long_settled_funding short_settled_funding: Decimal = layout.short_settled_funding + bids_quantity: Decimal = layout.bids_quantity + asks_quantity: Decimal = layout.asks_quantity + taker_base: Decimal = layout.taker_base + taker_quote: Decimal = layout.taker_quote mngo_accrued_raw: Decimal = layout.mngo_accrued mngo_accrued: TokenValue = TokenValue(mngo_token, mngo_token.shift_to_decimals(mngo_accrued_raw)) - open_orders: PerpOpenOrders = PerpOpenOrders.from_layout(layout.open_orders) - - return PerpAccount(base_position, quote_position, long_settled_funding, short_settled_funding, mngo_accrued, open_orders) + return PerpAccount(base_position, quote_position, long_settled_funding, short_settled_funding, + bids_quantity, asks_quantity, taker_base, taker_quote, mngo_accrued, open_orders) def __str__(self) -> str: - if self.base_position == Decimal(0) and self.quote_position == Decimal(0) and self.long_settled_funding == Decimal(0) and self.short_settled_funding == Decimal(0) and self.mngo_accrued.value == Decimal(0) and self.open_orders.free_slot_bits == 0xFFFFFFFF: + if self.base_position == Decimal(0) and self.quote_position == Decimal(0) and self.long_settled_funding == Decimal(0) and self.short_settled_funding == Decimal(0) and self.mngo_accrued.value == Decimal(0) and self.open_orders.empty: return "Β« π™ΏπšŽπš›πš™π™°πšŒπšŒπš˜πšžπš—πš (empty) Β»" open_orders = f"{self.open_orders}".replace("\n", "\n ") return f"""Β« π™ΏπšŽπš›πš™π™°πšŒπšŒπš˜πšžπš—πš @@ -58,6 +67,10 @@ class PerpAccount: Quote Position: {self.quote_position} Long Settled Funding: {self.long_settled_funding} Short Settled Funding: {self.short_settled_funding} + Bids Quantity: {self.bids_quantity} + Asks Quantity: {self.asks_quantity} + Taker Base: {self.taker_base} + Taker Quote: {self.taker_quote} MNGO Accrued: {self.mngo_accrued} OpenOrders: {open_orders} diff --git a/mango/perpmarketinstructionbuilder.py b/mango/perpmarketinstructionbuilder.py index 730a500..3f34386 100644 --- a/mango/perpmarketinstructionbuilder.py +++ b/mango/perpmarketinstructionbuilder.py @@ -51,11 +51,11 @@ class PerpMarketInstructionBuilder(MarketInstructionBuilder): def load(context: Context, wallet: Wallet, group: Group, account: Account, perp_market: PerpMarket) -> "PerpMarketInstructionBuilder": return PerpMarketInstructionBuilder(context, wallet, group, account, perp_market) - def build_cancel_order_instructions(self, order: Order) -> CombinableInstructions: + def build_cancel_order_instructions(self, order: Order, ok_if_missing: bool = False) -> CombinableInstructions: if self.perp_market.underlying_perp_market is None: raise Exception(f"PerpMarket {self.perp_market.symbol} has not been loaded.") return build_cancel_perp_order_instructions( - self.context, self.wallet, self.account, self.perp_market.underlying_perp_market, order) + self.context, self.wallet, self.account, self.perp_market.underlying_perp_market, order, ok_if_missing) def build_place_order_instructions(self, order: Order) -> CombinableInstructions: if self.perp_market.underlying_perp_market is None: diff --git a/mango/perpmarketoperations.py b/mango/perpmarketoperations.py index dbc3d8a..a180407 100644 --- a/mango/perpmarketoperations.py +++ b/mango/perpmarketoperations.py @@ -46,10 +46,11 @@ class PerpMarketOperations(MarketOperations): self.account: Account = account self.perp_market: PerpMarket = perp_market - def cancel_order(self, order: Order) -> typing.Sequence[str]: + def cancel_order(self, order: Order, ok_if_missing: bool = False) -> typing.Sequence[str]: self.logger.info(f"Cancelling {self.market_name} order {order}.") signers: CombinableInstructions = CombinableInstructions.from_wallet(self.wallet) - cancel: CombinableInstructions = self.market_instruction_builder.build_cancel_order_instructions(order) + cancel: CombinableInstructions = self.market_instruction_builder.build_cancel_order_instructions( + order, ok_if_missing=ok_if_missing) accounts_to_crank = self.perp_market.accounts_to_crank(self.context, self.account.address) crank = self.market_instruction_builder.build_crank_instructions(accounts_to_crank) settle = self.market_instruction_builder.build_settle_instructions() diff --git a/mango/perpopenorders.py b/mango/perpopenorders.py index f1446d4..3c8a5ff 100644 --- a/mango/perpopenorders.py +++ b/mango/perpopenorders.py @@ -16,40 +16,23 @@ import typing -from decimal import Decimal - -from .layouts import layouts from .openorders import PlacedOrder # # πŸ₯­ PerpOpenOrders class # class PerpOpenOrders: - def __init__(self, bids_quantity: Decimal, asks_quantity: Decimal, free_slot_bits: Decimal, - is_bid_bits: Decimal, placed_orders: typing.Sequence[PlacedOrder]): - self.bids_quantity: Decimal = bids_quantity - self.asks_quantity: Decimal = asks_quantity - self.free_slot_bits: Decimal = free_slot_bits - self.is_bid_bits: Decimal = is_bid_bits + def __init__(self, placed_orders: typing.Sequence[PlacedOrder]): self.placed_orders: typing.Sequence[PlacedOrder] = placed_orders - @staticmethod - def from_layout(layout: layouts.PERP_OPEN_ORDERS) -> "PerpOpenOrders": - bids_quantity: Decimal = layout.bids_quantity - asks_quantity: Decimal = layout.asks_quantity - free_slot_bits: Decimal = layout.free_slot_bits - is_bid_bits: Decimal = layout.is_bid_bits - - placed_orders = PlacedOrder.build_from_open_orders_data( - layout.free_slot_bits, layout.is_bid_bits, layout.orders, layout.client_order_ids) - return PerpOpenOrders(bids_quantity, asks_quantity, free_slot_bits, is_bid_bits, placed_orders) + @property + def empty(self) -> bool: + return len(self.placed_orders) == 0 def __str__(self) -> str: placed_orders = "\n ".join(map(str, self.placed_orders)) or "None" return f"""Β« π™ΏπšŽπš›πš™π™Ύπš™πšŽπš—π™Ύπš›πšπšŽπš›πšœ - Bids Quantity: {self.bids_quantity} - Asks Quantity: {self.asks_quantity} Orders: {placed_orders} Β»""" diff --git a/mango/serummarketinstructionbuilder.py b/mango/serummarketinstructionbuilder.py index 7a01b94..a20c2d5 100644 --- a/mango/serummarketinstructionbuilder.py +++ b/mango/serummarketinstructionbuilder.py @@ -83,7 +83,7 @@ class SerumMarketInstructionBuilder(MarketInstructionBuilder): return SerumMarketInstructionBuilder(context, wallet, serum_market, raw_market, base_token_account, quote_token_account, open_orders_address, fee_discount_token_address) - def build_cancel_order_instructions(self, order: Order) -> CombinableInstructions: + def build_cancel_order_instructions(self, order: Order, ok_if_missing: bool = False) -> CombinableInstructions: # For us to cancel an order, an open_orders account must already exist (or have existed). if self.open_orders_address is None: raise Exception(f"Cannot cancel order with client ID {order.client_id} - no OpenOrders account.") diff --git a/mango/serummarketoperations.py b/mango/serummarketoperations.py index c466839..538f308 100644 --- a/mango/serummarketoperations.py +++ b/mango/serummarketoperations.py @@ -42,10 +42,11 @@ class SerumMarketOperations(MarketOperations): self.serum_market: SerumMarket = serum_market self.market_instruction_builder: SerumMarketInstructionBuilder = market_instruction_builder - def cancel_order(self, order: Order) -> typing.Sequence[str]: + def cancel_order(self, order: Order, ok_if_missing: bool = False) -> typing.Sequence[str]: self.logger.info(f"Cancelling {self.serum_market.symbol} order {order}.") signers: CombinableInstructions = CombinableInstructions.from_wallet(self.wallet) - cancel: CombinableInstructions = self.market_instruction_builder.build_cancel_order_instructions(order) + cancel: CombinableInstructions = self.market_instruction_builder.build_cancel_order_instructions( + order, ok_if_missing=ok_if_missing) crank: CombinableInstructions = self._build_crank() settle: CombinableInstructions = self.market_instruction_builder.build_settle_instructions() return (signers + cancel + crank + settle).execute(self.context) diff --git a/mango/spotmarketinstructionbuilder.py b/mango/spotmarketinstructionbuilder.py index 4ac88a0..ffea905 100644 --- a/mango/spotmarketinstructionbuilder.py +++ b/mango/spotmarketinstructionbuilder.py @@ -83,7 +83,7 @@ class SpotMarketInstructionBuilder(MarketInstructionBuilder): return SpotMarketInstructionBuilder(context, wallet, group, account, spot_market, raw_market, base_token_account, quote_token_account, market_index, fee_discount_token_address) - def build_cancel_order_instructions(self, order: Order) -> CombinableInstructions: + def build_cancel_order_instructions(self, order: Order, ok_if_missing: bool = False) -> CombinableInstructions: if self.open_orders_address is None: return CombinableInstructions.empty() diff --git a/mango/spotmarketoperations.py b/mango/spotmarketoperations.py index 90c108f..bab0872 100644 --- a/mango/spotmarketoperations.py +++ b/mango/spotmarketoperations.py @@ -49,10 +49,11 @@ class SpotMarketOperations(MarketOperations): self.market_index: int = group.find_spot_market_index(spot_market.address) self.open_orders_address: typing.Optional[PublicKey] = self.account.spot_open_orders[self.market_index] - def cancel_order(self, order: Order) -> typing.Sequence[str]: + def cancel_order(self, order: Order, ok_if_missing: bool = False) -> typing.Sequence[str]: self.logger.info(f"Cancelling {self.spot_market.symbol} order {order}.") signers: CombinableInstructions = CombinableInstructions.from_wallet(self.wallet) - cancel: CombinableInstructions = self.market_instruction_builder.build_cancel_order_instructions(order) + cancel: CombinableInstructions = self.market_instruction_builder.build_cancel_order_instructions( + order, ok_if_missing=ok_if_missing) crank: CombinableInstructions = self._build_crank(add_self=True) settle: CombinableInstructions = self.market_instruction_builder.build_settle_instructions() diff --git a/tests/test_context.py b/tests/test_context.py index ab72a61..3694641 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -7,7 +7,7 @@ def context_has_default_values(ctx): assert ctx.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E") assert ctx.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY") assert ctx.group_name == "devnet.1" - assert ctx.group_id == PublicKey("D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM") + assert ctx.group_id == PublicKey("4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4") def test_context_default_exists(): @@ -27,7 +27,7 @@ def test_context_default_values(): # assert derived.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E") # assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY") # assert derived.group_name == "devnet.1" -# assert derived.group_id == PublicKey("D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM") +# assert derived.group_id == PublicKey("4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4") # context_has_default_values(mango.ContextBuilder.default()) @@ -37,7 +37,7 @@ def test_new_from_cluster_url(): assert derived.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E") assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY") assert derived.group_name == "devnet.1" - assert derived.group_id == PublicKey("D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM") + assert derived.group_id == PublicKey("4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4") context_has_default_values(mango.ContextBuilder.default()) @@ -49,17 +49,17 @@ def test_new_from_group_name(): # Should update both of these values on new group name. assert derived.group_name == "devnet.1" - assert derived.group_id == PublicKey("D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM") + assert derived.group_id == PublicKey("4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4") context_has_default_values(mango.ContextBuilder.default()) def test_new_from_group_id(): context_has_default_values(mango.ContextBuilder.default()) - derived = mango.ContextBuilder.default().new_from_group_id(PublicKey("D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM")) + derived = mango.ContextBuilder.default().new_from_group_id(PublicKey("4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4")) assert derived.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E") assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY") # Should update both of these values on new group ID. assert derived.group_name == "devnet.1" - assert derived.group_id == PublicKey("D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM") + assert derived.group_id == PublicKey("4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4") context_has_default_values(mango.ContextBuilder.default())