Updated to latest group structures and IDs.
This commit is contained in:
parent
847628dfd6
commit
97a5c41a39
261
data/ids.json
261
data/ids.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"cluster_urls": {
|
"cluster_urls": {
|
||||||
"devnet": "https://mango.devnet.rpcpool.com",
|
"devnet": "https://api.devnet.solana.com",
|
||||||
"localnet": "http://127.0.0.1:8899",
|
"localnet": "http://127.0.0.1:8899",
|
||||||
"mainnet-beta": "https://solana-api.projectserum.com",
|
"mainnet-beta": "https://solana-api.projectserum.com",
|
||||||
"testnet": "https://testnet.solana.com"
|
"testnet": "https://testnet.solana.com"
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
{
|
{
|
||||||
"cluster": "devnet",
|
"cluster": "devnet",
|
||||||
"name": "devnet.1",
|
"name": "devnet.1",
|
||||||
"publicKey": "D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM",
|
"publicKey": "4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4",
|
||||||
"quoteSymbol": "USDC",
|
"quoteSymbol": "USDC",
|
||||||
"mangoProgramId": "5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E",
|
"mangoProgramId": "5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E",
|
||||||
"serumProgramId": "DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY",
|
"serumProgramId": "DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY",
|
||||||
|
@ -18,106 +18,79 @@
|
||||||
"symbol": "USDC",
|
"symbol": "USDC",
|
||||||
"mintKey": "8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN",
|
"mintKey": "8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN",
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"rootKey": "J2PZBR4M8V4LXDG8oPC8BG1t8JUSXHC6fSMCxR9tFdfZ",
|
"rootKey": "8HomaswMsbUtfdYeFd6zKBFfdzWZ8KqW7beu3wpJi6zE",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"9iXA2Y3UPqJJE6qe7TtRcxGdqYcToKh8sCZv88Jt4dXS"
|
"F7hQduZSp8jvFKH1LAkYByDhzKoJFeKTGqz2JzeT1fby"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "MNGO",
|
"symbol": "MNGO",
|
||||||
"mintKey": "Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC",
|
"mintKey": "Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC",
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"rootKey": "1UBCGeMVmoNHt7Ldj7L6aj29f8oxRhuvCGwjJnTW1yU",
|
"rootKey": "scfyRHbzBnEyeELkVq8LP3QyNKZfzdF8AESmPqtqqc7",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"G9zKrvZhCgkAU6QUW37NjghKMBnmBdDzk3aYgbE6ZkJY"
|
"8A5QQKXGHnMUsPiBQN4dJeVDnJjjHQTeExUpqsBaRFVv"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "BTC",
|
"symbol": "BTC",
|
||||||
"mintKey": "3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU",
|
"mintKey": "3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU",
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"rootKey": "YyuJod2J35HhUYPq1gkregZjaD3Zr2m3MdZaUrmh74W",
|
"rootKey": "5peczazimSQpLiqpo9JeZeZJAhr6BvDxTkKLrQHQqW6u",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"CKjPnjQdHPDJDFKAevSCpLJ8NQk7UrsbCgbXQAh1AXgu"
|
"6AYdrMRPRdhWVGHaw9qVXcvbXAPn3xNH73bTvbG48c5L"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "ETH",
|
"symbol": "ETH",
|
||||||
"mintKey": "Cu84KB3tDL6SbFgToHMLYVDJJXdJjenNzSKikeAvzmkA",
|
"mintKey": "Cu84KB3tDL6SbFgToHMLYVDJJXdJjenNzSKikeAvzmkA",
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"rootKey": "Anjg6i35hDE3VTCRXcSTYaUMctMc6Wx5TrpJkVF2g2Uc",
|
"rootKey": "AKQLYJXdqMUxRMGskbxSrCUFB9hV2PXy7CgcwdCEiKKb",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"6kHBxELNpRhQ1D7DdNtZUZHeqV72kDPjhJb9Mqkpm8h"
|
"5iNkcp9cHuebGuvg7hkND19LDYEm5rz5hg73MyaCWgiZ"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "SOL",
|
"symbol": "SOL",
|
||||||
"mintKey": "So11111111111111111111111111111111111111112",
|
"mintKey": "So11111111111111111111111111111111111111112",
|
||||||
"decimals": 9,
|
"decimals": 9,
|
||||||
"rootKey": "TSA9ikdc4fHJEGbkEEcGeXk4Snk3REd91Vvk67PCB8U",
|
"rootKey": "2i1USFkMnUrLGyF6HDWYw5VtPfDjpfL6bhjSyiCRMFS7",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"5XYKTZgoWfLQK8zmngNefLi6zE5J3LiUXZrfyfVRpy67"
|
"DzTqkCiD9Lb3e8tX5ozFzjwUmaHN8nfNGqLmYg1MHxvA"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "SRM",
|
"symbol": "SRM",
|
||||||
"mintKey": "AvtB6w9xboLwA145E221vhof5TddhqsChYcx7Fy3xVMH",
|
"mintKey": "AvtB6w9xboLwA145E221vhof5TddhqsChYcx7Fy3xVMH",
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"rootKey": "A3swcrvcnVTa1kaamjfxikxJrTRe3PVjAKb4ke3MqU2L",
|
"rootKey": "BodzTbB412CwnkJbDG6rQpvAy9MHPgqskpH4r7qn3nB7",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"EoL6ZSxXKKVPZyNYMSqF44JMxUFK7w4bwqXXb95i8sMZ"
|
"H9hkW2DtyrETf7EGmeiz9QdChf9thk5FFRb4HAXfC5An"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "RAY",
|
"symbol": "RAY",
|
||||||
"mintKey": "3YFQ7UYJ7sNGpXTKBxM3bYLVxKpzVudXAe4gLExh5b3n",
|
"mintKey": "3YFQ7UYJ7sNGpXTKBxM3bYLVxKpzVudXAe4gLExh5b3n",
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"rootKey": "BGjFGQsocyTHQ87q8Sm6veM2fvrswbS9swfPwv1VPu4w",
|
"rootKey": "6NUEWYb2v4zc2dxeWPfswGZDLzjqaYzHG8bThctHG7jz",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"HbAproJH9NDXS4BNHtfeqvQQ6M7QCwvkHs79PCAJ62pb"
|
"DBAAoG5d21YouJinh5vgk9VBowPWfzXNbhBsPW2XisEb"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"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"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "USDT",
|
"symbol": "USDT",
|
||||||
"mintKey": "DAwBSXe6w9g37wdE2tCrFbho3QHKZi4PjuBytQCULap2",
|
"mintKey": "DAwBSXe6w9g37wdE2tCrFbho3QHKZi4PjuBytQCULap2",
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"rootKey": "HyncqkGfvmDf8CCXXTSYcPGJk9MfkoW7mm4hfHZ6EEZk",
|
"rootKey": "4Z1Yq3PotHzgdxhvj5q3tmhAWrbRZZpNtKGpjyAdJugD",
|
||||||
"nodeKeys": [
|
"nodeKeys": [
|
||||||
"91fZLKyYCXxxrfVrCogY1MJdqe9RBUQPvdWwncedMD9u"
|
"D6weykQ7DSzHKZQpFW59Z8gRduRFJAxxoM3p5Zn2N7FG"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"oracles": [
|
"oracles": [
|
||||||
{
|
{
|
||||||
"symbol": "MNGO",
|
"symbol": "MNGO",
|
||||||
"publicKey": "9qNwk4nFs2FzqqBNcbEfQwzYEGALsuuZz7qqV4UTyyrN"
|
"publicKey": "2s7XrK1c7tmT4GNuSzzPcTBHFWLKmNZh8vi3UUYCWyqL"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "BTC",
|
"symbol": "BTC",
|
||||||
|
@ -137,19 +110,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "RAY",
|
"symbol": "RAY",
|
||||||
"publicKey": "DySvRB195HvXbPCz4VU1KS7q2DrpAMoKAPDWRsMRzx4k"
|
"publicKey": "8jLbp5tcdWpqATwuFwwQ5eBPWsDxaFopJqnXhxmD6caN"
|
||||||
},
|
|
||||||
{
|
|
||||||
"symbol": "DOGE",
|
|
||||||
"publicKey": "4L6YhY8VvUgmqG5MvJkUJATtzB2rFqdrJwQCmFLv4Jzy"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"symbol": "SUSHI",
|
|
||||||
"publicKey": "AmALh5D5d27r3kBsTctwCcK9oV2bYy168y7DjgT8vTnc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"symbol": "FTT",
|
|
||||||
"publicKey": "6vivTRs5ZPeeXbjo7dfburfaYDWoXjBtdtuYgQRuGfu"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"symbol": "USDT",
|
"symbol": "USDT",
|
||||||
|
@ -159,225 +120,159 @@
|
||||||
"perpMarkets": [
|
"perpMarkets": [
|
||||||
{
|
{
|
||||||
"name": "MNGO-PERP",
|
"name": "MNGO-PERP",
|
||||||
"publicKey": "Eb9kbaZN5im9RiyJJi9j231vdGjwHqk9U87BTH8vozHn",
|
"publicKey": "GB4QffZnSGVmCh2qscTxGVwkqBSt7NB8B5fpuRcDFCFD",
|
||||||
"baseSymbol": "MNGO",
|
"baseSymbol": "MNGO",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 0,
|
"marketIndex": 0,
|
||||||
"bidsKey": "8DioiDW4L9UWf2kfKFY1kcsLMcVWESavAfct8z6JBGaY",
|
"bidsKey": "9a3FU66bknYPSPAFG5Wmv3hFCoJ2VMpdrefZUPdGJyMJ",
|
||||||
"asksKey": "4Bk1VDtXDtKQAxS31kpdJmVs5AXUd3DaGt1PEgtW26cR",
|
"asksKey": "5cx3XqHQU8vY5qPrbEccqTvuzXdgEwcbCbHDSD9fVoGE",
|
||||||
"eventsKey": "HfACePStB6PcrAGA6YKBPscXEm7kDhLwML98xmcQ55gW"
|
"eventsKey": "BiJ6kg2ncPt3HPJctM1bYoBWHXzvwWhD7AB883tiNWzr"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "BTC-PERP",
|
"name": "BTC-PERP",
|
||||||
"publicKey": "5FePG6TGQ2PybQVmFvKbCEXEYKmohoCUmz91zzVCqrTU",
|
"publicKey": "CekAcHL8x6XjMXYNCfTFrs4rAAYkNCdir2LCdjJHdmCB",
|
||||||
"baseSymbol": "BTC",
|
"baseSymbol": "BTC",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 1,
|
"marketIndex": 1,
|
||||||
"bidsKey": "GE9szLB8GvtqDH5QN9CuovzKDdSXuY1oGHQGwKyk4hTT",
|
"bidsKey": "8Mx11pN2Vj9bRH3DHqu9XdFp7My7VYjM3FL1TyY9tZ6z",
|
||||||
"asksKey": "BxJEW9AewNwBf8RSn7LLjpGmueKrSL5QX8WhDXwTaeb2",
|
"asksKey": "fJ8goLHFpdtbSY6uaKVRGP2WH21csAip7B8QRagVwjt",
|
||||||
"eventsKey": "CxCVE8pNJUihmaGzK2eLSb9XZ2XQR4r2xpJk7brZj4kX"
|
"eventsKey": "HNxDQsf8ntqmZy6YDuWrWQieuYjLTaucq652tpf6jFXN"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ETH-PERP",
|
"name": "ETH-PERP",
|
||||||
"publicKey": "9GHN7VGxNSCaSiDtTeZkT4ZseqVVkCTKw7VYEAaJqiNc",
|
"publicKey": "1h3QZQjo4X4bnJAPignsgfEebaJvhAyYJ22n5Asj2Aq",
|
||||||
"baseSymbol": "ETH",
|
"baseSymbol": "ETH",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 2,
|
"marketIndex": 2,
|
||||||
"bidsKey": "9bPCjgu17vtaSMe4ojWCEBumd1KmttweUPHVnfakaodt",
|
"bidsKey": "BQy6FyJZ5Nn8pfScyLmmxmzpWjJEdyx7Wgxd8Amx2sE6",
|
||||||
"asksKey": "8VhKgHYdeVTFvPrn1zeA6iHfvAtFXQnSKDLsk38YhZ8n",
|
"asksKey": "J3Buki4SKYZUZZq2KhouEaPQi9C7CyNCJn7SFaRCTn1V",
|
||||||
"eventsKey": "FPgTy3JmLKck9jyQzBFAmRGq8G4WmifeXq6CJJMivGtb"
|
"eventsKey": "EYkinFh4MvyknVWc8VSr5ofqoW7RN2WccYWRsPB9LFKH"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SOL-PERP",
|
"name": "SOL-PERP",
|
||||||
"publicKey": "Htds23imNxeeR778DLXHXDjUnr2sFYdtj31tz6hwSZnV",
|
"publicKey": "8bdzbDmK776L7SYo15jFrCE1jZpGJ5Hvi3HCX4nkG2SC",
|
||||||
"baseSymbol": "SOL",
|
"baseSymbol": "SOL",
|
||||||
"baseDecimals": 9,
|
"baseDecimals": 9,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 3,
|
"marketIndex": 3,
|
||||||
"bidsKey": "8fD5gMavPbRMJd4KMFopLF6fzhKMQZHwH5wMZMxLkMJe",
|
"bidsKey": "36j8vFEy8MFSEZ1qbgNBZ85bfLir3m2JWK1Xyfod3SXq",
|
||||||
"asksKey": "3AdnHLkNw9qm4vwRsjgs9KffkCSZr5JvGLEgFx6QBJaM",
|
"asksKey": "6gfw77TVq2dasBGrbNQNfUEjj1qH8yfTZxQdsqm1czGB",
|
||||||
"eventsKey": "7nMo3Apws96PqEP4ejnoJTQimc9DRsz91NV32wHasQEZ"
|
"eventsKey": "CKh8QDgvGrVY1anhL6uWcTqSTkPkZqMs2ijvYJcVd4N4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SRM-PERP",
|
"name": "SRM-PERP",
|
||||||
"publicKey": "8j8JEHSduFv8L8tw4AybTTRzELKQbu2xnjcTUdxZ8SZ2",
|
"publicKey": "H1zA6828E6pitokeK7bjo9bNGmcQnUAEzNDVymnjgnSo",
|
||||||
"baseSymbol": "SRM",
|
"baseSymbol": "SRM",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 4,
|
"marketIndex": 4,
|
||||||
"bidsKey": "ExRkH8dUbeTADeffrpV8kFw3P12s5Ya8K4fvQ4iUgru7",
|
"bidsKey": "674JmaAdzSfUJ163tq1mL53zPrAU3xEn67n4oCBJwQ1U",
|
||||||
"asksKey": "6AiXmTA9c1eG7vmDuckNUTM3qdV9KpCsi2UvVTSYWA9r",
|
"asksKey": "6oRDC75LQkQRwPbMftfdQLazp62hUHGDnuky9T5BZoU4",
|
||||||
"eventsKey": "6bhy7yUzZoPKMK4TdsnhDMs9CMRQQ8iqynkWqir9VTqg"
|
"eventsKey": "2sFGWmFEie8A123mXHf1C6rYbKhNEfcjbNThYDPQbVQ4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "RAY-PERP",
|
"name": "RAY-PERP",
|
||||||
"publicKey": "JCVKRwUG81Wpo3ErTCfWWZsuvRxECEtGRkLppRceef7X",
|
"publicKey": "9rt89vb7o2uEUUhM435YXCBE9nYzdxYqWfgbumDX5qDd",
|
||||||
"baseSymbol": "RAY",
|
"baseSymbol": "RAY",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 5,
|
"marketIndex": 5,
|
||||||
"bidsKey": "9M19Sk7ydE5omHBN5W2EF7idqtcPGMTPmwN4s2TY4BSS",
|
"bidsKey": "6hRYk2JJibhFFShZFZPqussECXNxCvi2oC38V2GwETPN",
|
||||||
"asksKey": "BpdPV6Q6zGeGb2jzr16RrMBNLSANxjxX8VuFr2sEwY1H",
|
"asksKey": "GBoPouNmbdmmpLCdEDzXhyoRfdQYofK7xD3vY8oZckRG",
|
||||||
"eventsKey": "G9GJ7ykDo165PwLFMdKYiXDsnmfzPGji6764Q9rU2VdD"
|
"eventsKey": "8Dy78QoWXufCwQNSLRKJ9bH1JcUho3GfRvbDqiyALQC7"
|
||||||
},
|
|
||||||
{
|
|
||||||
"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"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "USDT-PERP",
|
"name": "USDT-PERP",
|
||||||
"publicKey": "Djr75WctR92VCqssZ619qPJbKKZFjEMwi86mFdN4VfFi",
|
"publicKey": "HzA2xewTzqboVJk8yeSP9wqpSE4XHEmGMzsiFBmwCszE",
|
||||||
"baseSymbol": "USDT",
|
"baseSymbol": "USDT",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 9,
|
"marketIndex": 6,
|
||||||
"bidsKey": "8iJ7oHisRHsxAygGfp1ki9GZh8k2QwEirF6uUbr98XM3",
|
"bidsKey": "93n4jwHsbCEvZZ4cydyy7c8AHWY4LtPSdP6CLLjzJSw",
|
||||||
"asksKey": "bhJxk5Zc6SxbBbj6kEauYGvZaxzSCkYcWtwmQwMjfP3",
|
"asksKey": "BP2rC9v87xov554hcMVwRW5qB1qcRa27RXKTbA6YobwK",
|
||||||
"eventsKey": "GAayxsWfK7XVg3UXb79XS3CtuJSwFuzeLtEHvSfDSuoS"
|
"eventsKey": "GRUrFv3M5L5cPhMETkSTBssZZT2B9DdDwoeW2BQ3Jv1y"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spotMarkets": [
|
"spotMarkets": [
|
||||||
{
|
{
|
||||||
"name": "MNGO/USDC",
|
"name": "MNGO/USDC",
|
||||||
"publicKey": "BP5duanM1mEVyW6hi1fXz5KZmW15DpJuL3yR8V1bH3Py",
|
"publicKey": "D9KWifyaFX8qxyktRzzCLv4n37ameEoUP1jPkMdu13JZ",
|
||||||
"baseSymbol": "MNGO",
|
"baseSymbol": "MNGO",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 0,
|
"marketIndex": 0,
|
||||||
"bidsKey": "BBaYoN6utgyKMDNhKPqvREMNKbqj4sE7PPCr9cmFv7c8",
|
"bidsKey": "BEJD7DrCxv1GigvcXRZLsq8gr13h7ypwSNDYUTxAqjzj",
|
||||||
"asksKey": "6nRnAvEPQ6ycVRTzpp7s97BFfzDF7Niio5MoZ7Nowip9",
|
"asksKey": "AkXKeB1bpvieCGDKgcSDs1cvKDVvqemynq7Xpbvp23ic",
|
||||||
"eventsKey": "5EwoR3usrHeMPn9tFfXnpvibgmqB6QyMaNfk9jaZUtkZ"
|
"eventsKey": "5gnYPsN26T4hGDZYmuddG9aeRXZUpPGDNjn5a9vXThdj"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "BTC/USDC",
|
"name": "BTC/USDC",
|
||||||
"publicKey": "6LUe1qbDwoj3dmM4jvXwshRAcpMFH7xQ5dWyssAtAuHV",
|
"publicKey": "BYXAPyT9fKiyUJ162mqXbVmchQaEwMnrcenM9esDV4k5",
|
||||||
"baseSymbol": "BTC",
|
"baseSymbol": "BTC",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 1,
|
"marketIndex": 1,
|
||||||
"bidsKey": "8SCQybswfLSVQSZaDjACcj7kVBzG1nPhMxB4M4WmsGKp",
|
"bidsKey": "5wkoQDMYcrfuKB9Die5yLZTboWHcmW1M6yJXM5uhk66Z",
|
||||||
"asksKey": "D6wzhFJW6QZDotBuFWmy6e9rszQm9W5FR32Z8KtMGUbf",
|
"asksKey": "DBS7Zw5zFC58jVsqX8bRwSjtTc8ca5r27g6Y4ikr9hhv",
|
||||||
"eventsKey": "G4UuuNB92mquXqDJirV35ooWmHGqoD57zzG6FAbufCUu"
|
"eventsKey": "4hrYeHTGRGcEWkqLZqVwuMAmo1dtankVNML2psBBhkmT"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ETH/USDC",
|
"name": "ETH/USDC",
|
||||||
"publicKey": "6YzKiCwaURhEVEXxLBD8gNQXziCPqi6h17dhpH17NNFD",
|
"publicKey": "G7NYXEQ6W4mVoMinn9a8XaY4oswhW59NhtNWDQg5An2U",
|
||||||
"baseSymbol": "ETH",
|
"baseSymbol": "ETH",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 2,
|
"marketIndex": 2,
|
||||||
"bidsKey": "DYELab7pC4v78Q6n8YXEAzZqLJdVPXbHDuSQDX1z5kJV",
|
"bidsKey": "2RRd7yVxEhQzBBuNHBkR49SxWcQ8tSKv2D61DQo4DZVx",
|
||||||
"asksKey": "dWD2Kc3SbEDKvCtPxfeuBXLbk1o2NFhN47AG65gwwcz",
|
"asksKey": "69WSZeZ7KTky19XH1Z9g2ZMkZJEt8pweD2WZcw9heRNb",
|
||||||
"eventsKey": "Aen28QFiv6MaQDcbq58fz4Krttj5HXxvfpUr5js2sXoW"
|
"eventsKey": "Huy7jJX5fyuHtyWEN2xjjcSmEB18riqTFDCwUMsTtGm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SOL/USDC",
|
"name": "SOL/USDC",
|
||||||
"publicKey": "7GLPw3pdjpyf2YpXoXo1PTDa5WciT8NDNzz3PnMB1ZTM",
|
"publicKey": "6pV5PfVL6Ct5jiiySyt144ocMcuepLdAuF3umYMuh3rN",
|
||||||
"baseSymbol": "SOL",
|
"baseSymbol": "SOL",
|
||||||
"baseDecimals": 9,
|
"baseDecimals": 9,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 3,
|
"marketIndex": 3,
|
||||||
"bidsKey": "6DoTW6uKSJhfsK8CzLM9CWfTn4QjzF3gksPyLgcnZgys",
|
"bidsKey": "5N2KmqcnXSP2PE2Dg9UF2f1Y2kF7sdi8xTnzAwhqF8iv",
|
||||||
"asksKey": "4in1zY5zr7S7Rfg9txKzd7cgnHfNriQQH4LiwTd2MhGn",
|
"asksKey": "7U1XLt3mbQVYdNR7JoKoJyN8TfQUA6Lv5VDZaAKz3waa",
|
||||||
"eventsKey": "DDp6dFXwZxyzg65q5sfe58NCpps5nFuha5xS8Kb1EDgU"
|
"eventsKey": "34B9UoVjhUn7BXyXkfFHpQNWBZeGWhg9rJEBLgyocqiF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "SRM/USDC",
|
"name": "SRM/USDC",
|
||||||
"publicKey": "FM3NeE8ZhzcZXf2FtLGiSHTbLzQsemHh3emmBMLyFMDu",
|
"publicKey": "76JPTPeZr6UWzU4jcjLfGKAHfSywsXiwrgGo7dt7Kwzb",
|
||||||
"baseSymbol": "SRM",
|
"baseSymbol": "SRM",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 4,
|
"marketIndex": 4,
|
||||||
"bidsKey": "8aeTnuRxPuMZT6EjBxSuPiaKPVHah5gznq3mNszkDPkZ",
|
"bidsKey": "Dc4xX9VSV3R71jDKiMSPZqpa8EBhVo1GHZxkCMfVepkx",
|
||||||
"asksKey": "6eAGyCQg8vUNvBV96ztoArAKTudBGsr8XSaQbWWcvuXj",
|
"asksKey": "5bvsugaaA7c53eNdiVzuTG68pTPR4QGNK7CEYyC3PbML",
|
||||||
"eventsKey": "UgAd1bmJ3zr5MAUz8XpT5ku32HK73W8jCjyUwSvgQZM"
|
"eventsKey": "VvhudujDXLXCkwcDJXrMbtSBgMHdEjJrLys14fy6SQ9"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "RAY/USDC",
|
"name": "RAY/USDC",
|
||||||
"publicKey": "G8W9b1ACTKipefeCD8wrBTFygqCY48fX22hywFwE9ne8",
|
"publicKey": "CwBV7qFPkfRrJPao8jaoAK5NoWYVYSVgtaBvAXN7JZs7",
|
||||||
"baseSymbol": "RAY",
|
"baseSymbol": "RAY",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 5,
|
"marketIndex": 5,
|
||||||
"bidsKey": "8HQaw8X8ph2mqpFhGrD1FZC1VDfBkyw5gtTg6jkjCZPd",
|
"bidsKey": "H18vDMumfWDxgU6YVJb1D8fhahvkSUubzA7jU61q8RiP",
|
||||||
"asksKey": "77XVr3Ypgs8SNCem5N8wi97GQTGyrs16jEWw6nS1Bdsn",
|
"asksKey": "7D4TYmMVi8HpKu8Tg2CHV998HQe2iZj25B295MDdabdU",
|
||||||
"eventsKey": "4XcMk15DBK1cBsvKXRMo8m1AWZbnNpWjPBwKrhCLnVhN"
|
"eventsKey": "CGchuvhJjfMXy5Rh272eM6z8y7k6v8XH4UYJZSMUTjUP"
|
||||||
},
|
|
||||||
{
|
|
||||||
"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"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "USDT/USDC",
|
"name": "USDT/USDC",
|
||||||
"publicKey": "2jnUTkxsDvRmiZzWw1wpxuTnT1SbT6PmYFKNPbWdyY6U",
|
"publicKey": "97N64HezGkNs1sPBUMUxLLxkeCoBqSNzZmipxpeBcYUg",
|
||||||
"baseSymbol": "USDT",
|
"baseSymbol": "USDT",
|
||||||
"baseDecimals": 6,
|
"baseDecimals": 6,
|
||||||
"quoteDecimals": 6,
|
"quoteDecimals": 6,
|
||||||
"marketIndex": 9,
|
"marketIndex": 6,
|
||||||
"bidsKey": "C1gxQ8NjqnaFs9TC5U7de5YKfAyNpQTiYWQAjPHMDE91",
|
"bidsKey": "BoKZMtnEgzV1gtix6RotBq4wteNXteGFEyeTMC88BUyw",
|
||||||
"asksKey": "AhnGqCuTNzLiQ6Y4m2oxds2sog3u2ChX8MXCMYyaPCb4",
|
"asksKey": "EbgYUYhPTqFxMqc7pq2v9MWTbzu2m5frzvw6ePTsAFWq",
|
||||||
"eventsKey": "GBEkcp2qqu13qxtYFXJxER1W1bAww2yBj9tCmR9ZXUde"
|
"eventsKey": "38X8AuewBYZATEovYnXr7znDbiAxkxxEn7RYjXDtVn1T"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -156,7 +156,7 @@ def pulse(self, context: mango.Context, model_state: ModelState):
|
||||||
cancellations = mango.CombinableInstructions.empty()
|
cancellations = mango.CombinableInstructions.empty()
|
||||||
for to_cancel in reconciled.to_cancel:
|
for to_cancel in reconciled.to_cancel:
|
||||||
self.logger.info(f"Cancelling {self.market.symbol} {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
|
cancellations += cancel
|
||||||
|
|
||||||
place_orders = mango.CombinableInstructions.empty()
|
place_orders = mango.CombinableInstructions.empty()
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
# [Github](https://github.com/blockworks-foundation)
|
# [Github](https://github.com/blockworks-foundation)
|
||||||
# [Email](mailto:hello@blockworks.foundation)
|
# [Email](mailto:hello@blockworks.foundation)
|
||||||
|
|
||||||
|
from mango.perpopenorders import PerpOpenOrders
|
||||||
|
from mango.placedorder import PlacedOrder
|
||||||
from mango.tokeninfo import TokenInfo
|
from mango.tokeninfo import TokenInfo
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
|
@ -27,6 +29,7 @@ from .encoding import encode_key
|
||||||
from .group import Group
|
from .group import Group
|
||||||
from .layouts import layouts
|
from .layouts import layouts
|
||||||
from .metadata import Metadata
|
from .metadata import Metadata
|
||||||
|
from .orders import Side
|
||||||
from .perpaccount import PerpAccount
|
from .perpaccount import PerpAccount
|
||||||
from .token import Token
|
from .token import Token
|
||||||
from .tokenvalue import TokenValue
|
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])
|
in_margin_basket: typing.Sequence[bool] = list([bool(in_basket) for in_basket in layout.in_margin_basket])
|
||||||
active_in_basket: typing.List[bool] = []
|
active_in_basket: typing.List[bool] = []
|
||||||
basket: typing.List[AccountBasketBaseToken] = []
|
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]):
|
for index, token_info in enumerate(group.tokens[:-1]):
|
||||||
if token_info:
|
if token_info:
|
||||||
intrinsic_deposit = token_info.root_bank.deposit_index * layout.deposits[index]
|
intrinsic_deposit = token_info.root_bank.deposit_index * layout.deposits[index]
|
||||||
deposit = TokenValue(token_info.token, token_info.token.shift_to_decimals(intrinsic_deposit))
|
deposit = TokenValue(token_info.token, token_info.token.shift_to_decimals(intrinsic_deposit))
|
||||||
intrinsic_borrow = token_info.root_bank.borrow_index * layout.borrows[index]
|
intrinsic_borrow = token_info.root_bank.borrow_index * layout.borrows[index]
|
||||||
borrow = TokenValue(token_info.token, token_info.token.shift_to_decimals(intrinsic_borrow))
|
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]
|
spot_open_orders = layout.spot_open_orders[index]
|
||||||
basket_item: AccountBasketBaseToken = AccountBasketBaseToken(
|
basket_item: AccountBasketBaseToken = AccountBasketBaseToken(
|
||||||
token_info, deposit, borrow, spot_open_orders, perp_account)
|
token_info, deposit, borrow, spot_open_orders, perp_account)
|
||||||
|
|
|
@ -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.
|
# Prefer cancelling by client ID so we don't have to keep track of the order side.
|
||||||
if order.client_id != 0:
|
if order.client_id != 0:
|
||||||
data: bytes = layouts.CANCEL_PERP_ORDER_BY_CLIENT_ID.build(
|
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:
|
else:
|
||||||
# { buy: 0, sell: 1 }
|
|
||||||
raw_side: int = 1 if order.side == Side.SELL else 0
|
|
||||||
data = layouts.CANCEL_PERP_ORDER.build(
|
data = layouts.CANCEL_PERP_ORDER.build(
|
||||||
{
|
{
|
||||||
"order_id": order.id,
|
"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):
|
# 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]
|
base_token_info = base_token_infos[0]
|
||||||
quote_token_info = group.shared_quote_token
|
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
|
base_root_bank: RootBank = base_token_info.root_bank
|
||||||
node_bank: NodeBank = root_bank.pick_node_bank(context)
|
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] = []
|
fee_discount_address_meta: typing.List[AccountMeta] = []
|
||||||
if fee_discount_address is not None:
|
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.event_queue()),
|
||||||
AccountMeta(is_signer=False, is_writable=True, pubkey=market.state.base_vault()),
|
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=True, pubkey=market.state.quote_vault()),
|
||||||
AccountMeta(is_signer=False, is_writable=False, pubkey=root_bank.address),
|
AccountMeta(is_signer=False, is_writable=False, pubkey=base_root_bank.address),
|
||||||
AccountMeta(is_signer=False, is_writable=True, pubkey=node_bank.address),
|
AccountMeta(is_signer=False, is_writable=True, pubkey=base_node_bank.address),
|
||||||
AccountMeta(is_signer=False, is_writable=True, pubkey=node_bank.vault),
|
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=TOKEN_PROGRAM_ID),
|
||||||
AccountMeta(is_signer=False, is_writable=False, pubkey=group.signer_key),
|
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=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),
|
*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]),
|
pubkey=oo_address or SYSTEM_PROGRAM_ADDRESS) for oo_address in account.spot_open_orders]),
|
||||||
*fee_discount_address_meta
|
*fee_discount_address_meta
|
||||||
|
|
|
@ -326,6 +326,7 @@ MAX_NODE_BANKS: int = 8
|
||||||
QUOTE_INDEX: int = MAX_TOKENS - 1
|
QUOTE_INDEX: int = MAX_TOKENS - 1
|
||||||
MAX_BOOK_NODES: int = 1024
|
MAX_BOOK_NODES: int = 1024
|
||||||
MAX_ORDERS: int = 32
|
MAX_ORDERS: int = 32
|
||||||
|
MAX_PERP_OPEN_ORDERS: int = 64
|
||||||
|
|
||||||
DATA_TYPE = construct.Enum(construct.Int8ul, Group=0, Account=1, RootBank=2,
|
DATA_TYPE = construct.Enum(construct.Int8ul, Group=0, Account=1, RootBank=2,
|
||||||
NodeBank=3, PerpMarket=4, Bids=5, Asks=6, Cache=7, EventQueue=8)
|
NodeBank=3, PerpMarket=4, Bids=5, Asks=6, Cache=7, EventQueue=8)
|
||||||
|
@ -541,30 +542,6 @@ NODE_BANK = construct.Struct(
|
||||||
"vault" / PublicKeyAdapter()
|
"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
|
# # 🥭 PERP_ACCOUNT
|
||||||
#
|
#
|
||||||
# Here's the [Rust structure](https://github.com/blockworks-foundation/mango-v3/blob/main/program/src/state.rs):
|
# 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 long_settled_funding: I80F48,
|
||||||
# pub short_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(
|
PERP_ACCOUNT = construct.Struct(
|
||||||
"base_position" / SignedDecimalAdapter(),
|
"base_position" / SignedDecimalAdapter(),
|
||||||
"quote_position" / FloatI80F48Adapter(),
|
"quote_position" / FloatI80F48Adapter(),
|
||||||
|
|
||||||
"long_settled_funding" / FloatI80F48Adapter(),
|
"long_settled_funding" / FloatI80F48Adapter(),
|
||||||
"short_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(),
|
"mngo_accrued" / DecimalAdapter(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -596,6 +588,7 @@ PERP_ACCOUNT = construct.Struct(
|
||||||
# ```
|
# ```
|
||||||
# pub const INFO_LEN: usize = 32;
|
# pub const INFO_LEN: usize = 32;
|
||||||
# pub const MAX_NUM_IN_MARGIN_BASKET: u8 = 10;
|
# pub const MAX_NUM_IN_MARGIN_BASKET: u8 = 10;
|
||||||
|
# pub const MAX_PERP_OPEN_ORDERS: usize = 64;
|
||||||
# #[derive(Copy, Clone, Pod, Loadable)]
|
# #[derive(Copy, Clone, Pod, Loadable)]
|
||||||
# #[repr(C)]
|
# #[repr(C)]
|
||||||
# pub struct MangoAccount {
|
# pub struct MangoAccount {
|
||||||
|
@ -615,7 +608,13 @@ PERP_ACCOUNT = construct.Struct(
|
||||||
# // Perps related data
|
# // Perps related data
|
||||||
# pub perp_accounts: [PerpAccount; MAX_PAIRS],
|
# 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,
|
# pub msrm_amount: u64,
|
||||||
|
#
|
||||||
# /// This account cannot open new positions or borrow until `init_health >= 0`
|
# /// This account cannot open new positions or borrow until `init_health >= 0`
|
||||||
# pub being_liquidated: bool,
|
# pub being_liquidated: bool,
|
||||||
#
|
#
|
||||||
|
@ -636,6 +635,10 @@ MANGO_ACCOUNT = construct.Struct(
|
||||||
"borrows" / construct.Array(MAX_TOKENS, FloatI80F48Adapter()),
|
"borrows" / construct.Array(MAX_TOKENS, FloatI80F48Adapter()),
|
||||||
"spot_open_orders" / construct.Array(MAX_PAIRS, PublicKeyAdapter()),
|
"spot_open_orders" / construct.Array(MAX_PAIRS, PublicKeyAdapter()),
|
||||||
"perp_accounts" / construct.Array(MAX_PAIRS, PERP_ACCOUNT),
|
"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(),
|
"msrm_amount" / DecimalAdapter(),
|
||||||
"being_liquidated" / DecimalAdapter(1),
|
"being_liquidated" / DecimalAdapter(1),
|
||||||
"is_bankrupt" / DecimalAdapter(1),
|
"is_bankrupt" / DecimalAdapter(1),
|
||||||
|
@ -1203,7 +1206,7 @@ CANCEL_PERP_ORDER = construct.Struct(
|
||||||
"variant" / construct.Const(14, construct.BytesInteger(4, swapped=True)),
|
"variant" / construct.Const(14, construct.BytesInteger(4, swapped=True)),
|
||||||
|
|
||||||
"order_id" / DecimalAdapter(16),
|
"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(
|
CANCEL_PERP_ORDER_BY_CLIENT_ID = construct.Struct(
|
||||||
"variant" / construct.Const(13, construct.BytesInteger(4, swapped=True)),
|
"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.
|
# Run the Mango crank.
|
||||||
|
|
|
@ -47,7 +47,7 @@ class MarketInstructionBuilder(metaclass=abc.ABCMeta):
|
||||||
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
||||||
|
|
||||||
@abc.abstractmethod
|
@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(
|
raise NotImplementedError(
|
||||||
"MarketInstructionBuilder.build_cancel_order_instructions() is not implemented on the base type.")
|
"MarketInstructionBuilder.build_cancel_order_instructions() is not implemented on the base type.")
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ class NullMarketInstructionBuilder(MarketInstructionBuilder):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.symbol: str = symbol
|
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()
|
return CombinableInstructions.empty()
|
||||||
|
|
||||||
def build_place_order_instructions(self, order: Order) -> CombinableInstructions:
|
def build_place_order_instructions(self, order: Order) -> CombinableInstructions:
|
||||||
|
|
|
@ -63,7 +63,7 @@ class MarketMaker:
|
||||||
cancellations = mango.CombinableInstructions.empty()
|
cancellations = mango.CombinableInstructions.empty()
|
||||||
for to_cancel in reconciled.to_cancel:
|
for to_cancel in reconciled.to_cancel:
|
||||||
self.logger.info(f"Cancelling {self.market.symbol} {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
|
cancellations += cancel
|
||||||
|
|
||||||
place_orders = mango.CombinableInstructions.empty()
|
place_orders = mango.CombinableInstructions.empty()
|
||||||
|
|
|
@ -55,7 +55,7 @@ class MarketOperations(metaclass=abc.ABCMeta):
|
||||||
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
|
||||||
|
|
||||||
@abc.abstractmethod
|
@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.")
|
raise NotImplementedError("MarketOperations.cancel_order() is not implemented on the base type.")
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -93,7 +93,7 @@ class NullMarketOperations(MarketOperations):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.market_name: str = market_name
|
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}.")
|
self.logger.info(f"Cancelling order {order}.")
|
||||||
return [""]
|
return [""]
|
||||||
|
|
||||||
|
|
|
@ -28,29 +28,38 @@ from .tokenvalue import TokenValue
|
||||||
#
|
#
|
||||||
class PerpAccount:
|
class PerpAccount:
|
||||||
def __init__(self, base_position: Decimal, quote_position: Decimal, long_settled_funding: Decimal,
|
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.base_position: Decimal = base_position
|
||||||
self.quote_position: Decimal = quote_position
|
self.quote_position: Decimal = quote_position
|
||||||
self.long_settled_funding: Decimal = long_settled_funding
|
self.long_settled_funding: Decimal = long_settled_funding
|
||||||
self.short_settled_funding: Decimal = short_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.mngo_accrued: TokenValue = mngo_accrued
|
||||||
self.open_orders: PerpOpenOrders = open_orders
|
self.open_orders: PerpOpenOrders = open_orders
|
||||||
|
|
||||||
@staticmethod
|
@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
|
base_position: Decimal = layout.base_position
|
||||||
quote_position: Decimal = layout.quote_position
|
quote_position: Decimal = layout.quote_position
|
||||||
long_settled_funding: Decimal = layout.long_settled_funding
|
long_settled_funding: Decimal = layout.long_settled_funding
|
||||||
short_settled_funding: Decimal = layout.short_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_raw: Decimal = layout.mngo_accrued
|
||||||
mngo_accrued: TokenValue = TokenValue(mngo_token, mngo_token.shift_to_decimals(mngo_accrued_raw))
|
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,
|
||||||
|
bids_quantity, asks_quantity, taker_base, taker_quote, mngo_accrued, open_orders)
|
||||||
return PerpAccount(base_position, quote_position, long_settled_funding, short_settled_funding, mngo_accrued, open_orders)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
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) »"
|
return "« 𝙿𝚎𝚛𝚙𝙰𝚌𝚌𝚘𝚞𝚗𝚝 (empty) »"
|
||||||
open_orders = f"{self.open_orders}".replace("\n", "\n ")
|
open_orders = f"{self.open_orders}".replace("\n", "\n ")
|
||||||
return f"""« 𝙿𝚎𝚛𝚙𝙰𝚌𝚌𝚘𝚞𝚗𝚝
|
return f"""« 𝙿𝚎𝚛𝚙𝙰𝚌𝚌𝚘𝚞𝚗𝚝
|
||||||
|
@ -58,6 +67,10 @@ class PerpAccount:
|
||||||
Quote Position: {self.quote_position}
|
Quote Position: {self.quote_position}
|
||||||
Long Settled Funding: {self.long_settled_funding}
|
Long Settled Funding: {self.long_settled_funding}
|
||||||
Short Settled Funding: {self.short_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}
|
MNGO Accrued: {self.mngo_accrued}
|
||||||
OpenOrders:
|
OpenOrders:
|
||||||
{open_orders}
|
{open_orders}
|
||||||
|
|
|
@ -51,11 +51,11 @@ class PerpMarketInstructionBuilder(MarketInstructionBuilder):
|
||||||
def load(context: Context, wallet: Wallet, group: Group, account: Account, perp_market: PerpMarket) -> "PerpMarketInstructionBuilder":
|
def load(context: Context, wallet: Wallet, group: Group, account: Account, perp_market: PerpMarket) -> "PerpMarketInstructionBuilder":
|
||||||
return PerpMarketInstructionBuilder(context, wallet, group, account, perp_market)
|
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:
|
if self.perp_market.underlying_perp_market is None:
|
||||||
raise Exception(f"PerpMarket {self.perp_market.symbol} has not been loaded.")
|
raise Exception(f"PerpMarket {self.perp_market.symbol} has not been loaded.")
|
||||||
return build_cancel_perp_order_instructions(
|
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:
|
def build_place_order_instructions(self, order: Order) -> CombinableInstructions:
|
||||||
if self.perp_market.underlying_perp_market is None:
|
if self.perp_market.underlying_perp_market is None:
|
||||||
|
|
|
@ -46,10 +46,11 @@ class PerpMarketOperations(MarketOperations):
|
||||||
self.account: Account = account
|
self.account: Account = account
|
||||||
self.perp_market: PerpMarket = perp_market
|
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}.")
|
self.logger.info(f"Cancelling {self.market_name} order {order}.")
|
||||||
signers: CombinableInstructions = CombinableInstructions.from_wallet(self.wallet)
|
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)
|
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)
|
crank = self.market_instruction_builder.build_crank_instructions(accounts_to_crank)
|
||||||
settle = self.market_instruction_builder.build_settle_instructions()
|
settle = self.market_instruction_builder.build_settle_instructions()
|
||||||
|
|
|
@ -16,40 +16,23 @@
|
||||||
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
from .layouts import layouts
|
|
||||||
from .openorders import PlacedOrder
|
from .openorders import PlacedOrder
|
||||||
|
|
||||||
|
|
||||||
# # 🥭 PerpOpenOrders class
|
# # 🥭 PerpOpenOrders class
|
||||||
#
|
#
|
||||||
class PerpOpenOrders:
|
class PerpOpenOrders:
|
||||||
def __init__(self, bids_quantity: Decimal, asks_quantity: Decimal, free_slot_bits: Decimal,
|
def __init__(self, placed_orders: typing.Sequence[PlacedOrder]):
|
||||||
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
|
|
||||||
self.placed_orders: typing.Sequence[PlacedOrder] = placed_orders
|
self.placed_orders: typing.Sequence[PlacedOrder] = placed_orders
|
||||||
|
|
||||||
@staticmethod
|
@property
|
||||||
def from_layout(layout: layouts.PERP_OPEN_ORDERS) -> "PerpOpenOrders":
|
def empty(self) -> bool:
|
||||||
bids_quantity: Decimal = layout.bids_quantity
|
return len(self.placed_orders) == 0
|
||||||
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)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
placed_orders = "\n ".join(map(str, self.placed_orders)) or "None"
|
placed_orders = "\n ".join(map(str, self.placed_orders)) or "None"
|
||||||
|
|
||||||
return f"""« 𝙿𝚎𝚛𝚙𝙾𝚙𝚎𝚗𝙾𝚛𝚍𝚎𝚛𝚜
|
return f"""« 𝙿𝚎𝚛𝚙𝙾𝚙𝚎𝚗𝙾𝚛𝚍𝚎𝚛𝚜
|
||||||
Bids Quantity: {self.bids_quantity}
|
|
||||||
Asks Quantity: {self.asks_quantity}
|
|
||||||
Orders:
|
Orders:
|
||||||
{placed_orders}
|
{placed_orders}
|
||||||
»"""
|
»"""
|
||||||
|
|
|
@ -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)
|
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).
|
# For us to cancel an order, an open_orders account must already exist (or have existed).
|
||||||
if self.open_orders_address is None:
|
if self.open_orders_address is None:
|
||||||
raise Exception(f"Cannot cancel order with client ID {order.client_id} - no OpenOrders account.")
|
raise Exception(f"Cannot cancel order with client ID {order.client_id} - no OpenOrders account.")
|
||||||
|
|
|
@ -42,10 +42,11 @@ class SerumMarketOperations(MarketOperations):
|
||||||
self.serum_market: SerumMarket = serum_market
|
self.serum_market: SerumMarket = serum_market
|
||||||
self.market_instruction_builder: SerumMarketInstructionBuilder = market_instruction_builder
|
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}.")
|
self.logger.info(f"Cancelling {self.serum_market.symbol} order {order}.")
|
||||||
signers: CombinableInstructions = CombinableInstructions.from_wallet(self.wallet)
|
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()
|
crank: CombinableInstructions = self._build_crank()
|
||||||
settle: CombinableInstructions = self.market_instruction_builder.build_settle_instructions()
|
settle: CombinableInstructions = self.market_instruction_builder.build_settle_instructions()
|
||||||
return (signers + cancel + crank + settle).execute(self.context)
|
return (signers + cancel + crank + settle).execute(self.context)
|
||||||
|
|
|
@ -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)
|
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:
|
if self.open_orders_address is None:
|
||||||
return CombinableInstructions.empty()
|
return CombinableInstructions.empty()
|
||||||
|
|
||||||
|
|
|
@ -49,10 +49,11 @@ class SpotMarketOperations(MarketOperations):
|
||||||
self.market_index: int = group.find_spot_market_index(spot_market.address)
|
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]
|
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}.")
|
self.logger.info(f"Cancelling {self.spot_market.symbol} order {order}.")
|
||||||
signers: CombinableInstructions = CombinableInstructions.from_wallet(self.wallet)
|
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)
|
crank: CombinableInstructions = self._build_crank(add_self=True)
|
||||||
settle: CombinableInstructions = self.market_instruction_builder.build_settle_instructions()
|
settle: CombinableInstructions = self.market_instruction_builder.build_settle_instructions()
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ def context_has_default_values(ctx):
|
||||||
assert ctx.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E")
|
assert ctx.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E")
|
||||||
assert ctx.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
assert ctx.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
||||||
assert ctx.group_name == "devnet.1"
|
assert ctx.group_name == "devnet.1"
|
||||||
assert ctx.group_id == PublicKey("D3H3f29tcGNeEgk4bArKcRKQv8V4zCUFrj1sGXaHwgvM")
|
assert ctx.group_id == PublicKey("4XKVThVcLBdN9E2CDuuNmJejCVbVjqvb8VGjoGyHz8A4")
|
||||||
|
|
||||||
|
|
||||||
def test_context_default_exists():
|
def test_context_default_exists():
|
||||||
|
@ -27,7 +27,7 @@ def test_context_default_values():
|
||||||
# assert derived.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E")
|
# assert derived.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E")
|
||||||
# assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
# assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
||||||
# assert derived.group_name == "devnet.1"
|
# 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())
|
# 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.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E")
|
||||||
assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
||||||
assert derived.group_name == "devnet.1"
|
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())
|
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.
|
# Should update both of these values on new group name.
|
||||||
assert derived.group_name == "devnet.1"
|
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())
|
context_has_default_values(mango.ContextBuilder.default())
|
||||||
|
|
||||||
|
|
||||||
def test_new_from_group_id():
|
def test_new_from_group_id():
|
||||||
context_has_default_values(mango.ContextBuilder.default())
|
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.program_id == PublicKey("5fP7Z7a87ZEVsKr2tQPApdtq83GcTW4kz919R6ou5h5E")
|
||||||
assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
assert derived.dex_program_id == PublicKey("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY")
|
||||||
|
|
||||||
# Should update both of these values on new group ID.
|
# Should update both of these values on new group ID.
|
||||||
assert derived.group_name == "devnet.1"
|
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())
|
context_has_default_values(mango.ContextBuilder.default())
|
||||||
|
|
Loading…
Reference in New Issue