Updated to latest group structures and IDs.

This commit is contained in:
Geoff Taylor 2021-08-17 19:42:11 +01:00
parent 847628dfd6
commit 97a5c41a39
17 changed files with 196 additions and 273 deletions

View File

@ -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"
}
]
},

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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:

View File

@ -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()

View File

@ -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 [""]

View File

@ -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}

View File

@ -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:

View File

@ -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()

View File

@ -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}
»"""

View File

@ -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.")

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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())