Mango v3 integration (#19437)
* mango v3 integration Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * more instructions InitMangoAccount, Deposit, Withdraw, InitSpotOpenOrders, ConsumeEvents Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * add support for addPerpMarket Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * code review Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * make group config handling generic Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * code review Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * fix issue where rpc calls would be done infinitely - basically react useeffect (when to change) was not narrow enough + added some caching Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
parent
1828579580
commit
f7a5c0301a
|
@ -5,8 +5,10 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "explorer",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@blockworks-foundation/mango-client": "^3.0.12",
|
||||
"@bonfida/bot": "^0.5.3",
|
||||
"@metamask/jazzicon": "^2.0.0",
|
||||
"@project-serum/serum": "^0.13.58",
|
||||
|
@ -1306,6 +1308,308 @@
|
|||
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
|
||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client": {
|
||||
"version": "3.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@blockworks-foundation/mango-client/-/mango-client-3.0.12.tgz",
|
||||
"integrity": "sha512-gDwn2feXPMuyxb+mQXXJfAlyVLojnCifPbvxfRNikV4nswHQmPVQ1GhLzqAYXxqxANBiRlDB3uHISnnQp0Xqcw==",
|
||||
"dependencies": {
|
||||
"@project-serum/serum": "0.13.55",
|
||||
"@project-serum/sol-wallet-adapter": "^0.2.0",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/web3.js": "1.21.0",
|
||||
"big.js": "^6.1.1",
|
||||
"bigint-buffer": "^1.1.5",
|
||||
"bn.js": "^5.1.0",
|
||||
"borsh": "git+https://github.com/defactojob/borsh-js.git#field-mapper",
|
||||
"buffer-layout": "^1.2.1",
|
||||
"yargs": "^17.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.15.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@babel/runtime": {
|
||||
"version": "7.15.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz",
|
||||
"integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@project-serum/serum": {
|
||||
"version": "0.13.55",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/serum/-/serum-0.13.55.tgz",
|
||||
"integrity": "sha512-SPQ4NsuNbBJO3mLGnTYbjt47WCXoNIcW2C9xv0gNXyG62dxgONsAEEgErKv1gT34hWCMPsXFSpatnX6ppriq7w==",
|
||||
"dependencies": {
|
||||
"@project-serum/anchor": "^0.11.1",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/web3.js": "^1.21.0",
|
||||
"bn.js": "^5.1.2",
|
||||
"buffer-layout": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@project-serum/sol-wallet-adapter": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.2.5.tgz",
|
||||
"integrity": "sha512-Y0XHe+FXXJ7P8XZtx3luAlatO0ge2LdrZUCmqMSzJf+K+fko+qTYIBSUuWwO7y/O4brIXVReR1mEUvF6QKDF2w==",
|
||||
"dependencies": {
|
||||
"bs58": "^4.0.1",
|
||||
"eventemitter3": "^4.0.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@solana/web3.js": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@solana/spl-token": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz",
|
||||
"integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.10.5",
|
||||
"@solana/web3.js": "^1.21.0",
|
||||
"bn.js": "^5.1.0",
|
||||
"buffer": "6.0.3",
|
||||
"buffer-layout": "^1.2.0",
|
||||
"dotenv": "10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@solana/spl-token/node_modules/buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@solana/web3.js": {
|
||||
"version": "1.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.21.0.tgz",
|
||||
"integrity": "sha512-x1NXlF92tEjxuTxS0u4n9JV17UKk0Dn2L+qSWGvKOb4iWhzApDj6wicJsrGdSbGdxnZ7eciQ/SNn3zB4ydUllA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@solana/buffer-layout": "^3.0.0",
|
||||
"bn.js": "^5.0.0",
|
||||
"borsh": "^0.4.0",
|
||||
"bs58": "^4.0.1",
|
||||
"buffer": "6.0.1",
|
||||
"crypto-hash": "^1.2.2",
|
||||
"jayson": "^3.4.4",
|
||||
"js-sha3": "^0.8.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"rpc-websockets": "^7.4.2",
|
||||
"secp256k1": "^4.0.2",
|
||||
"superstruct": "^0.14.2",
|
||||
"tweetnacl": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@solana/web3.js/node_modules/borsh": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/borsh/-/borsh-0.4.0.tgz",
|
||||
"integrity": "sha512-aX6qtLya3K0AkT66CmYWCCDr77qsE9arV05OmdFpmat9qu8Pg9J5tBUPDztAW5fNh/d/MyVG/OYziP52Ndzx1g==",
|
||||
"dependencies": {
|
||||
"@types/bn.js": "^4.11.5",
|
||||
"bn.js": "^5.0.0",
|
||||
"bs58": "^4.0.0",
|
||||
"text-encoding-utf-8": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/@types/bn.js": {
|
||||
"version": "4.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
|
||||
"integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/big.js": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-6.1.1.tgz",
|
||||
"integrity": "sha512-1vObw81a8ylZO5ePrtMay0n018TcftpTA5HFKDaSuiUDBo8biRBtjIobw60OpwuvrGk+FsxKamqN4cnmj/eXdg==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bigjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/borsh": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "git+ssh://git@github.com/defactojob/borsh-js.git#33a0d24af281112c0a48efb3fa503f3212443de9",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/bn.js": "^4.11.5",
|
||||
"bn.js": "^5.0.0",
|
||||
"bs58": "^4.0.0",
|
||||
"text-encoding-utf-8": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/dotenv": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/superstruct": {
|
||||
"version": "0.14.2",
|
||||
"resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz",
|
||||
"integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ=="
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/yargs": {
|
||||
"version": "17.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz",
|
||||
"integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==",
|
||||
"dependencies": {
|
||||
"cliui": "^7.0.2",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.0",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^20.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@blockworks-foundation/mango-client/node_modules/yargs-parser": {
|
||||
"version": "20.2.9",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@bonfida/bot": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@bonfida/bot/-/bot-0.5.3.tgz",
|
||||
|
@ -5924,6 +6228,18 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/bigint-buffer": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz",
|
||||
"integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"bindings": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bignumber.js": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
|
||||
|
@ -6220,9 +6536,9 @@
|
|||
"integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g=="
|
||||
},
|
||||
"node_modules/buffer-layout": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.0.tgz",
|
||||
"integrity": "sha512-iiyRoho/ERzBUv6kFvfsrLNgTlVwOkqQcSQN7WrO3Y+c5SeuEhCn6+y1KwhM0V3ndptF5mI/RI44zkw0qcR5Jg==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz",
|
||||
"integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==",
|
||||
"engines": {
|
||||
"node": ">=4.5"
|
||||
}
|
||||
|
@ -26030,6 +26346,238 @@
|
|||
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
|
||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="
|
||||
},
|
||||
"@blockworks-foundation/mango-client": {
|
||||
"version": "3.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@blockworks-foundation/mango-client/-/mango-client-3.0.12.tgz",
|
||||
"integrity": "sha512-gDwn2feXPMuyxb+mQXXJfAlyVLojnCifPbvxfRNikV4nswHQmPVQ1GhLzqAYXxqxANBiRlDB3uHISnnQp0Xqcw==",
|
||||
"requires": {
|
||||
"@project-serum/serum": "0.13.55",
|
||||
"@project-serum/sol-wallet-adapter": "^0.2.0",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/web3.js": "1.21.0",
|
||||
"big.js": "^6.1.1",
|
||||
"bigint-buffer": "^1.1.5",
|
||||
"bn.js": "^5.1.0",
|
||||
"borsh": "git+https://github.com/defactojob/borsh-js.git#field-mapper",
|
||||
"buffer-layout": "^1.2.1",
|
||||
"yargs": "^17.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.15.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz",
|
||||
"integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@project-serum/serum": {
|
||||
"version": "0.13.55",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/serum/-/serum-0.13.55.tgz",
|
||||
"integrity": "sha512-SPQ4NsuNbBJO3mLGnTYbjt47WCXoNIcW2C9xv0gNXyG62dxgONsAEEgErKv1gT34hWCMPsXFSpatnX6ppriq7w==",
|
||||
"requires": {
|
||||
"@project-serum/anchor": "^0.11.1",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/web3.js": "^1.21.0",
|
||||
"bn.js": "^5.1.2",
|
||||
"buffer-layout": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@project-serum/sol-wallet-adapter": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.2.5.tgz",
|
||||
"integrity": "sha512-Y0XHe+FXXJ7P8XZtx3luAlatO0ge2LdrZUCmqMSzJf+K+fko+qTYIBSUuWwO7y/O4brIXVReR1mEUvF6QKDF2w==",
|
||||
"requires": {
|
||||
"bs58": "^4.0.1",
|
||||
"eventemitter3": "^4.0.7"
|
||||
}
|
||||
},
|
||||
"@solana/spl-token": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz",
|
||||
"integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.10.5",
|
||||
"@solana/web3.js": "^1.21.0",
|
||||
"bn.js": "^5.1.0",
|
||||
"buffer": "6.0.3",
|
||||
"buffer-layout": "^1.2.0",
|
||||
"dotenv": "10.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||
"requires": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@solana/web3.js": {
|
||||
"version": "1.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.21.0.tgz",
|
||||
"integrity": "sha512-x1NXlF92tEjxuTxS0u4n9JV17UKk0Dn2L+qSWGvKOb4iWhzApDj6wicJsrGdSbGdxnZ7eciQ/SNn3zB4ydUllA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@solana/buffer-layout": "^3.0.0",
|
||||
"bn.js": "^5.0.0",
|
||||
"borsh": "^0.4.0",
|
||||
"bs58": "^4.0.1",
|
||||
"buffer": "6.0.1",
|
||||
"crypto-hash": "^1.2.2",
|
||||
"jayson": "^3.4.4",
|
||||
"js-sha3": "^0.8.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"rpc-websockets": "^7.4.2",
|
||||
"secp256k1": "^4.0.2",
|
||||
"superstruct": "^0.14.2",
|
||||
"tweetnacl": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"borsh": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/borsh/-/borsh-0.4.0.tgz",
|
||||
"integrity": "sha512-aX6qtLya3K0AkT66CmYWCCDr77qsE9arV05OmdFpmat9qu8Pg9J5tBUPDztAW5fNh/d/MyVG/OYziP52Ndzx1g==",
|
||||
"requires": {
|
||||
"@types/bn.js": "^4.11.5",
|
||||
"bn.js": "^5.0.0",
|
||||
"bs58": "^4.0.0",
|
||||
"text-encoding-utf-8": "^1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/bn.js": {
|
||||
"version": "4.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
|
||||
"integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"big.js": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-6.1.1.tgz",
|
||||
"integrity": "sha512-1vObw81a8ylZO5ePrtMay0n018TcftpTA5HFKDaSuiUDBo8biRBtjIobw60OpwuvrGk+FsxKamqN4cnmj/eXdg=="
|
||||
},
|
||||
"borsh": {
|
||||
"version": "git+ssh://git@github.com/defactojob/borsh-js.git#33a0d24af281112c0a48efb3fa503f3212443de9",
|
||||
"from": "borsh@git+https://github.com/defactojob/borsh-js.git#field-mapper",
|
||||
"requires": {
|
||||
"@types/bn.js": "^4.11.5",
|
||||
"bn.js": "^5.0.0",
|
||||
"bs58": "^4.0.0",
|
||||
"text-encoding-utf-8": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"superstruct": {
|
||||
"version": "0.14.2",
|
||||
"resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz",
|
||||
"integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ=="
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"requires": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "17.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz",
|
||||
"integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==",
|
||||
"requires": {
|
||||
"cliui": "^7.0.2",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.0",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^20.2.2"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "20.2.9",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@bonfida/bot": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@bonfida/bot/-/bot-0.5.3.tgz",
|
||||
|
@ -29875,6 +30423,14 @@
|
|||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
|
||||
},
|
||||
"bigint-buffer": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz",
|
||||
"integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==",
|
||||
"requires": {
|
||||
"bindings": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
|
||||
|
@ -30150,9 +30706,9 @@
|
|||
"integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g=="
|
||||
},
|
||||
"buffer-layout": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.0.tgz",
|
||||
"integrity": "sha512-iiyRoho/ERzBUv6kFvfsrLNgTlVwOkqQcSQN7WrO3Y+c5SeuEhCn6+y1KwhM0V3ndptF5mI/RI44zkw0qcR5Jg=="
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz",
|
||||
"integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA=="
|
||||
},
|
||||
"buffer-xor": {
|
||||
"version": "1.0.3",
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@blockworks-foundation/mango-client": "^3.0.12",
|
||||
"@bonfida/bot": "^0.5.3",
|
||||
"@metamask/jazzicon": "^2.0.0",
|
||||
"@project-serum/serum": "^0.13.58",
|
||||
|
|
|
@ -51,6 +51,7 @@ import { useQuery } from "utils/url";
|
|||
import { TokenInfoMap } from "@solana/spl-token-registry";
|
||||
import { useTokenRegistry } from "providers/mints/token-registry";
|
||||
import { getTokenProgramInstructionName } from "utils/instruction";
|
||||
import { isMangoInstruction, parseMangoInstructionTitle } from "components/instruction/mango/types";
|
||||
|
||||
const TRUNCATE_TOKEN_LENGTH = 10;
|
||||
const ALL_TOKENS = "";
|
||||
|
@ -502,6 +503,16 @@ const TokenTransactionRow = React.memo(
|
|||
reportError(error, { signature: tx.signature });
|
||||
return undefined;
|
||||
}
|
||||
} else if (
|
||||
transactionInstruction &&
|
||||
isMangoInstruction(transactionInstruction)
|
||||
) {
|
||||
try {
|
||||
name = parseMangoInstructionTitle(transactionInstruction);
|
||||
} catch (error) {
|
||||
reportError(error, { signature: tx.signature });
|
||||
return undefined;
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
ix.accounts.findIndex((account) =>
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { useCluster } from "providers/cluster";
|
||||
import { reportError } from "utils/sentry";
|
||||
import { InstructionCard } from "./InstructionCard";
|
||||
import { AddOracleDetailsCard } from "./mango/AddOracleDetailsCard";
|
||||
import { AddPerpMarketDetailsCard } from "./mango/AddPerpMarketDetailsCard";
|
||||
import { AddSpotMarketDetailsCard } from "./mango/AddSpotMarketDetailsCard";
|
||||
import { CancelPerpOrderDetailsCard } from "./mango/CancelPerpOrderDetailsCard";
|
||||
import { CancelSpotOrderDetailsCard } from "./mango/CancelSpotOrderDetailsCard";
|
||||
import { ChangePerpMarketParamsDetailsCard } from "./mango/ChangePerpMarketParamsDetailsCard";
|
||||
import { ConsumeEventsDetailsCard } from "./mango/ConsumeEventsDetailsCard";
|
||||
import { GenericMngoAccountDetailsCard } from "./mango/GenericMngoAccountDetailsCard";
|
||||
import { GenericPerpMngoDetailsCard } from "./mango/GenericPerpMngoDetailsCard";
|
||||
import { GenericSpotMngoDetailsCard } from "./mango/GenericSpotMngoDetailsCard";
|
||||
import { PlacePerpOrderDetailsCard } from "./mango/PlacePerpOrderDetailsCard";
|
||||
import { PlaceSpotOrderDetailsCard } from "./mango/PlaceSpotOrderDetailsCard";
|
||||
import {
|
||||
decodeAddPerpMarket,
|
||||
decodeAddSpotMarket,
|
||||
decodeCancelPerpOrder,
|
||||
decodeCancelSpotOrder,
|
||||
decodeChangePerpMarketParams,
|
||||
decodePlacePerpOrder,
|
||||
decodePlaceSpotOrder,
|
||||
parseMangoInstructionTitle,
|
||||
} from "./mango/types";
|
||||
|
||||
export function MangoDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
signature: string;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, signature, innerCards, childIndex } = props;
|
||||
|
||||
const { url } = useCluster();
|
||||
|
||||
let title;
|
||||
try {
|
||||
title = parseMangoInstructionTitle(ix);
|
||||
|
||||
switch (title) {
|
||||
case "InitMangoAccount":
|
||||
return (
|
||||
<GenericMngoAccountDetailsCard
|
||||
mangoAccountKeyLocation={1}
|
||||
title={title}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "Deposit":
|
||||
return (
|
||||
<GenericMngoAccountDetailsCard
|
||||
mangoAccountKeyLocation={1}
|
||||
title={title}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "Withdraw":
|
||||
return (
|
||||
<GenericMngoAccountDetailsCard
|
||||
mangoAccountKeyLocation={1}
|
||||
title={title}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "InitSpotOpenOrders":
|
||||
return (
|
||||
<GenericMngoAccountDetailsCard
|
||||
mangoAccountKeyLocation={1}
|
||||
title={title}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "PlaceSpotOrder":
|
||||
return (
|
||||
<PlaceSpotOrderDetailsCard
|
||||
info={decodePlaceSpotOrder(ix)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "CancelSpotOrder":
|
||||
return (
|
||||
<CancelSpotOrderDetailsCard
|
||||
info={decodeCancelSpotOrder(ix)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "AddPerpMarket":
|
||||
return (
|
||||
<AddPerpMarketDetailsCard info={decodeAddPerpMarket(ix)} {...props} />
|
||||
);
|
||||
case "PlacePerpOrder":
|
||||
return (
|
||||
<PlacePerpOrderDetailsCard
|
||||
info={decodePlacePerpOrder(ix)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "ConsumeEvents":
|
||||
return <ConsumeEventsDetailsCard {...props} />;
|
||||
case "CancelPerpOrder":
|
||||
return (
|
||||
<CancelPerpOrderDetailsCard
|
||||
info={decodeCancelPerpOrder(ix)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "SettleFunds":
|
||||
return (
|
||||
<GenericSpotMngoDetailsCard
|
||||
accountKeyLocation={2}
|
||||
spotMarketkeyLocation={5}
|
||||
title={title}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "RedeemMngo":
|
||||
return (
|
||||
<GenericPerpMngoDetailsCard
|
||||
mangoAccountKeyLocation={3}
|
||||
perpMarketKeyLocation={4}
|
||||
title={title}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "ChangePerpMarketParams":
|
||||
return (
|
||||
<ChangePerpMarketParamsDetailsCard
|
||||
info={decodeChangePerpMarketParams(ix)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
case "AddOracle":
|
||||
return <AddOracleDetailsCard {...props} />;
|
||||
case "AddSpotMarket":
|
||||
return (
|
||||
<AddSpotMarketDetailsCard info={decodeAddSpotMarket(ix)} {...props} />
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
reportError(error, {
|
||||
url: url,
|
||||
signature: signature,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title={`Mango: ${title || "Unknown"}`}
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
defaultRaw
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
|
||||
export function AddOracleDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, innerCards, childIndex } = props;
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: AddOracle"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
></InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import moment from "moment";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import { AddPerpMarket } from "./types";
|
||||
|
||||
export function AddPerpMarketDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
info: AddPerpMarket;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, info, innerCards, childIndex } = props;
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: AddPerpMarket"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Market index</td>
|
||||
<td className="text-lg-right">{info.marketIndex}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Maintenance leverage</td>
|
||||
<td className="text-lg-right">{info.maintLeverage}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Initial leverage</td>
|
||||
<td className="text-lg-right">{info.initLeverage}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Liquidation fee</td>
|
||||
<td className="text-lg-right">{info.liquidationFee}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Maker fee</td>
|
||||
<td className="text-lg-right">{info.makerFee}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taker fee</td>
|
||||
<td className="text-lg-right">{info.takerFee}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Base lot size</td>
|
||||
<td className="text-lg-right">{info.baseLotSize}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Quote lot size</td>
|
||||
<td className="text-lg-right">{info.quoteLotSize}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rate</td>
|
||||
<td className="text-lg-right">{info.rate}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Max depth bps</td>
|
||||
<td className="text-lg-right">{info.maxDepthBps}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
MNGO per{" "}
|
||||
{moment.duration(info.targetPeriodLength, "seconds").humanize()}
|
||||
</td>
|
||||
<td className="text-lg-right">
|
||||
{info.mngoPerPeriod} {}
|
||||
</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import { AddSpotMarket, spotMarketFromIndex } from "./types";
|
||||
|
||||
export function AddSpotMarketDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
info: AddSpotMarket;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, info, innerCards, childIndex } = props;
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: AddSpotMarket"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
{spotMarketFromIndex(ix, info.marketIndex) !== "UNKNOWN" && (
|
||||
<tr>
|
||||
<td>Market</td>
|
||||
<td className="text-lg-right">
|
||||
{spotMarketFromIndex(ix, info.marketIndex)}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
<td>Market index</td>
|
||||
<td className="text-lg-right">{info.marketIndex}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Maint leverage</td>
|
||||
<td className="text-lg-right">{info.maintLeverage}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Init leverage</td>
|
||||
<td className="text-lg-right">{info.initLeverage}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Liquidation fee</td>
|
||||
<td className="text-lg-right">{info.liquidationFee}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimal util</td>
|
||||
<td className="text-lg-right">{info.optimalUtil}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimal rate</td>
|
||||
<td className="text-lg-right">{info.optimalRate}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Max rate</td>
|
||||
<td className="text-lg-right">{info.maxRate}</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import { CancelPerpOrder, getPerpMarketFromInstruction } from "./types";
|
||||
|
||||
export function CancelPerpOrderDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
info: CancelPerpOrder;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, info, innerCards, childIndex } = props;
|
||||
const mangoAccount = ix.keys[1];
|
||||
const perpMarketAccountMeta = ix.keys[3];
|
||||
const mangoPerpMarketConfig = getPerpMarketFromInstruction(
|
||||
ix,
|
||||
perpMarketAccountMeta
|
||||
);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: CancelPerpOrder"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Mango account</td>
|
||||
<td>
|
||||
<Address pubkey={mangoAccount.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{mangoPerpMarketConfig !== undefined && (
|
||||
<tr>
|
||||
<td>Perp market</td>
|
||||
<td className="text-lg-right">{mangoPerpMarketConfig.name}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Perp market address</td>
|
||||
<td>
|
||||
<Address pubkey={perpMarketAccountMeta.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Order Id</td>
|
||||
<td className="text-lg-right">{info.orderId}</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import { CancelSpotOrder, getSpotMarketFromInstruction } from "./types";
|
||||
|
||||
export function CancelSpotOrderDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
info: CancelSpotOrder;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, info, innerCards, childIndex } = props;
|
||||
const mangoAccount = ix.keys[2];
|
||||
const spotMarketAccountMeta = ix.keys[4];
|
||||
const mangoSpotMarketConfig = getSpotMarketFromInstruction(
|
||||
ix,
|
||||
spotMarketAccountMeta
|
||||
);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: CancelSpotOrder"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Mango account</td>
|
||||
<td>
|
||||
<Address pubkey={mangoAccount.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{mangoSpotMarketConfig !== undefined && (
|
||||
<tr>
|
||||
<td>Spot market</td>
|
||||
<td className="text-lg-right">{mangoSpotMarketConfig.name}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Spot market address</td>
|
||||
<td>
|
||||
<Address pubkey={spotMarketAccountMeta.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Order Id</td>
|
||||
<td className="text-lg-right">{info.orderId}</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import moment from "moment";
|
||||
import { useCluster } from "providers/cluster";
|
||||
import { useEffect, useState } from "react";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import {
|
||||
ChangePerpMarketParams,
|
||||
getPerpMarketFromInstruction,
|
||||
getPerpMarketFromPerpMarketConfig,
|
||||
} from "./types";
|
||||
|
||||
export function ChangePerpMarketParamsDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
info: ChangePerpMarketParams;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, info, innerCards, childIndex } = props;
|
||||
|
||||
const perpMarketAccountMeta = ix.keys[1];
|
||||
const mangoPerpMarketConfig = getPerpMarketFromInstruction(
|
||||
ix,
|
||||
perpMarketAccountMeta
|
||||
);
|
||||
|
||||
const cluster = useCluster();
|
||||
const [targetPeriodLength, setTargetPeriodLength] = useState<number | null>(
|
||||
null
|
||||
);
|
||||
useEffect(() => {
|
||||
async function getTargetPeriodLength() {
|
||||
if (mangoPerpMarketConfig === undefined) {
|
||||
return;
|
||||
}
|
||||
const mangoPerpMarket = await getPerpMarketFromPerpMarketConfig(
|
||||
cluster.url,
|
||||
mangoPerpMarketConfig
|
||||
);
|
||||
|
||||
setTargetPeriodLength(
|
||||
mangoPerpMarket.liquidityMiningInfo.targetPeriodLength.toNumber()
|
||||
);
|
||||
}
|
||||
|
||||
getTargetPeriodLength();
|
||||
}, [cluster.url, mangoPerpMarketConfig]);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: ChangePerpMarketParams"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
{info.initLeverageOption && (
|
||||
<tr>
|
||||
<td>Init leverage</td>
|
||||
<td className="text-lg-right">{info.initLeverage}</td>
|
||||
</tr>
|
||||
)}
|
||||
{info.liquidationFeeOption && (
|
||||
<tr>
|
||||
<td>Liquidation fee</td>
|
||||
<td className="text-lg-right">{info.liquidationFee}</td>
|
||||
</tr>
|
||||
)}
|
||||
{info.maintLeverageOption && (
|
||||
<tr>
|
||||
<td>Maint leverage</td>
|
||||
<td className="text-lg-right">{info.maintLeverage}</td>
|
||||
</tr>
|
||||
)}
|
||||
{info.makerFeeOption && (
|
||||
<tr>
|
||||
<td>Maker fee</td>
|
||||
<td className="text-lg-right">{info.makerFee}</td>
|
||||
</tr>
|
||||
)}
|
||||
{info.mngoPerPeriodOption && (
|
||||
<tr>
|
||||
<td>
|
||||
MNGO per{" "}
|
||||
{targetPeriodLength !== null &&
|
||||
moment.duration(targetPeriodLength, "seconds").humanize()}
|
||||
</td>
|
||||
<td className="text-lg-right">
|
||||
{info.mngoPerPeriod} {}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
{info.maxDepthBpsOption && (
|
||||
<tr>
|
||||
<td>Max depth bps</td>
|
||||
<td className="text-lg-right">{info.maxDepthBps}</td>
|
||||
</tr>
|
||||
)}
|
||||
{info.rateOption && (
|
||||
<tr>
|
||||
<td>Rate</td>
|
||||
<td className="text-lg-right">{info.rate}</td>
|
||||
</tr>
|
||||
)}
|
||||
{info.takerFeeOption && (
|
||||
<tr>
|
||||
<td>Taker fee</td>
|
||||
<td className="text-lg-right">{info.takerFee}</td>
|
||||
</tr>
|
||||
)}
|
||||
{info.targetPeriodLengthOption && (
|
||||
<tr>
|
||||
<td>Target period length</td>
|
||||
<td className="text-lg-right">{info.targetPeriodLength}</td>
|
||||
</tr>
|
||||
)}
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import { getPerpMarketFromInstruction } from "./types";
|
||||
|
||||
export function ConsumeEventsDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, innerCards, childIndex } = props;
|
||||
|
||||
const perpMarketAccountMeta = ix.keys[2];
|
||||
const mangoPerpMarketConfig = getPerpMarketFromInstruction(
|
||||
ix,
|
||||
perpMarketAccountMeta
|
||||
);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title={"Mango: ConsumeEvents"}
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
{mangoPerpMarketConfig !== undefined && (
|
||||
<tr>
|
||||
<td>Perp market</td>
|
||||
<td className="text-lg-right">{mangoPerpMarketConfig.name}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Perp market address</td>
|
||||
<td>
|
||||
<Address pubkey={perpMarketAccountMeta.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
|
||||
export function GenericMngoAccountDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
mangoAccountKeyLocation: number;
|
||||
title: String;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const {
|
||||
ix,
|
||||
index,
|
||||
result,
|
||||
mangoAccountKeyLocation,
|
||||
title,
|
||||
innerCards,
|
||||
childIndex,
|
||||
} = props;
|
||||
const mangoAccount = ix.keys[mangoAccountKeyLocation];
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title={"Mango: " + title}
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Mango account</td>
|
||||
<td>
|
||||
<Address pubkey={mangoAccount.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import { getPerpMarketFromInstruction } from "./types";
|
||||
|
||||
export function GenericPerpMngoDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
mangoAccountKeyLocation: number;
|
||||
perpMarketKeyLocation: number;
|
||||
title: String;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const {
|
||||
ix,
|
||||
index,
|
||||
result,
|
||||
mangoAccountKeyLocation,
|
||||
perpMarketKeyLocation,
|
||||
title,
|
||||
innerCards,
|
||||
childIndex,
|
||||
} = props;
|
||||
const mangoAccount = ix.keys[mangoAccountKeyLocation];
|
||||
const perpMarketAccountMeta = ix.keys[perpMarketKeyLocation];
|
||||
const mangoPerpMarketConfig = getPerpMarketFromInstruction(
|
||||
ix,
|
||||
perpMarketAccountMeta
|
||||
);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title={"Mango: " + title}
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Mango account</td>
|
||||
<td>
|
||||
<Address pubkey={mangoAccount.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{mangoPerpMarketConfig !== undefined && (
|
||||
<tr>
|
||||
<td>Perp market</td>
|
||||
<td className="text-lg-right">{mangoPerpMarketConfig.name}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Perp market address</td>
|
||||
<td>
|
||||
<Address pubkey={perpMarketAccountMeta.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import { getSpotMarketFromInstruction } from "./types";
|
||||
|
||||
export function GenericSpotMngoDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
accountKeyLocation: number;
|
||||
spotMarketkeyLocation: number;
|
||||
title: String;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const {
|
||||
ix,
|
||||
index,
|
||||
result,
|
||||
accountKeyLocation,
|
||||
spotMarketkeyLocation,
|
||||
title,
|
||||
innerCards,
|
||||
childIndex,
|
||||
} = props;
|
||||
const mangoAccount = ix.keys[accountKeyLocation];
|
||||
const spotMarketAccountMeta = ix.keys[spotMarketkeyLocation];
|
||||
const mangoSpotMarketConfig = getSpotMarketFromInstruction(
|
||||
ix,
|
||||
spotMarketAccountMeta
|
||||
);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title={"Mango: " + title}
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Mango account</td>
|
||||
<td>
|
||||
<Address pubkey={mangoAccount.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{mangoSpotMarketConfig !== undefined && (
|
||||
<tr>
|
||||
<td>Spot market</td>
|
||||
<td className="text-lg-right">{mangoSpotMarketConfig.name}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Spot market address</td>
|
||||
<td>
|
||||
<Address pubkey={spotMarketAccountMeta.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import BN from "bn.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { useCluster } from "providers/cluster";
|
||||
import { useEffect, useState } from "react";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import {
|
||||
getPerpMarketFromInstruction,
|
||||
getPerpMarketFromPerpMarketConfig,
|
||||
OrderLotDetails,
|
||||
PlacePerpOrder,
|
||||
} from "./types";
|
||||
|
||||
export function PlacePerpOrderDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
info: PlacePerpOrder;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, info, innerCards, childIndex } = props;
|
||||
const mangoAccount = ix.keys[1];
|
||||
const perpMarketAccountMeta = ix.keys[4];
|
||||
const mangoPerpMarketConfig = getPerpMarketFromInstruction(
|
||||
ix,
|
||||
perpMarketAccountMeta
|
||||
);
|
||||
|
||||
const cluster = useCluster();
|
||||
const [orderLotDetails, setOrderLotDetails] =
|
||||
useState<OrderLotDetails | null>(null);
|
||||
useEffect(() => {
|
||||
async function getOrderLotDetails() {
|
||||
if (mangoPerpMarketConfig === undefined) {
|
||||
return;
|
||||
}
|
||||
const mangoPerpMarket = await getPerpMarketFromPerpMarketConfig(
|
||||
cluster.url,
|
||||
mangoPerpMarketConfig
|
||||
);
|
||||
const maxBaseQuantity = mangoPerpMarket.baseLotsToNumber(
|
||||
new BN(info.quantity.toString())
|
||||
);
|
||||
const limitPrice = mangoPerpMarket.priceLotsToNumber(
|
||||
new BN(info.price.toString())
|
||||
);
|
||||
setOrderLotDetails({
|
||||
price: limitPrice,
|
||||
size: maxBaseQuantity,
|
||||
} as OrderLotDetails);
|
||||
}
|
||||
getOrderLotDetails();
|
||||
}, [cluster.url, info.quantity, info.price, mangoPerpMarketConfig]);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: PlacePerpOrder"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Mango account</td>
|
||||
<td>
|
||||
{" "}
|
||||
<Address pubkey={mangoAccount.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{mangoPerpMarketConfig !== undefined && (
|
||||
<tr>
|
||||
<td>Perp market</td>
|
||||
<td className="text-lg-right">{mangoPerpMarketConfig.name}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Perp market address</td>
|
||||
<td>
|
||||
<Address pubkey={perpMarketAccountMeta.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{info.clientOrderId !== "0" && (
|
||||
<tr>
|
||||
<td>Client order Id</td>
|
||||
<td className="text-lg-right">{info.clientOrderId}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Order type</td>
|
||||
<td className="text-lg-right">{info.orderType}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>side</td>
|
||||
<td className="text-lg-right">{info.side}</td>
|
||||
</tr>
|
||||
|
||||
{orderLotDetails !== null && (
|
||||
<tr>
|
||||
<td>price</td>
|
||||
<td className="text-lg-right">{orderLotDetails?.price} USDC</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
{orderLotDetails !== null && (
|
||||
<tr>
|
||||
<td>quantity</td>
|
||||
<td className="text-lg-right">{orderLotDetails?.size}</td>
|
||||
</tr>
|
||||
)}
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
|
||||
import BN from "bn.js";
|
||||
import { Address } from "components/common/Address";
|
||||
import { useCluster } from "providers/cluster";
|
||||
import { useEffect, useState } from "react";
|
||||
import { InstructionCard } from "../InstructionCard";
|
||||
import {
|
||||
getSpotMarketFromInstruction,
|
||||
getSpotMarketFromSpotMarketConfig,
|
||||
OrderLotDetails,
|
||||
PlaceSpotOrder,
|
||||
} from "./types";
|
||||
|
||||
export function PlaceSpotOrderDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
info: PlaceSpotOrder;
|
||||
innerCards?: JSX.Element[];
|
||||
childIndex?: number;
|
||||
}) {
|
||||
const { ix, index, result, info, innerCards, childIndex } = props;
|
||||
const mangoAccount = ix.keys[1];
|
||||
const spotMarketAccountMeta = ix.keys[5];
|
||||
const mangoSpotMarketConfig = getSpotMarketFromInstruction(
|
||||
ix,
|
||||
spotMarketAccountMeta
|
||||
);
|
||||
|
||||
const cluster = useCluster();
|
||||
const [orderLotDetails, setOrderLotDetails] =
|
||||
useState<OrderLotDetails | null>(null);
|
||||
useEffect(() => {
|
||||
async function getOrderLotDetails() {
|
||||
if (mangoSpotMarketConfig === undefined) {
|
||||
return;
|
||||
}
|
||||
const mangoSpotMarket = await getSpotMarketFromSpotMarketConfig(
|
||||
ix.programId,
|
||||
cluster.url,
|
||||
mangoSpotMarketConfig
|
||||
);
|
||||
if (mangoSpotMarket === undefined) {
|
||||
return;
|
||||
}
|
||||
const maxBaseQuantity = mangoSpotMarket.baseSizeLotsToNumber(
|
||||
new BN(info.maxBaseQuantity.toString())
|
||||
);
|
||||
const limitPrice = mangoSpotMarket.priceLotsToNumber(
|
||||
new BN(info.limitPrice.toString())
|
||||
);
|
||||
setOrderLotDetails({
|
||||
price: limitPrice,
|
||||
size: maxBaseQuantity,
|
||||
} as OrderLotDetails);
|
||||
}
|
||||
getOrderLotDetails();
|
||||
}, [
|
||||
cluster.url,
|
||||
info.maxBaseQuantity,
|
||||
info.limitPrice,
|
||||
ix.programId,
|
||||
mangoSpotMarketConfig,
|
||||
]);
|
||||
|
||||
return (
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Mango: PlaceSpotOrder"
|
||||
innerCards={innerCards}
|
||||
childIndex={childIndex}
|
||||
>
|
||||
<tr>
|
||||
<td>Mango account</td>
|
||||
<td>
|
||||
{" "}
|
||||
<Address pubkey={mangoAccount.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{mangoSpotMarketConfig !== undefined && (
|
||||
<tr>
|
||||
<td>Spot market</td>
|
||||
<td className="text-lg-right">{mangoSpotMarketConfig.name}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Spot market address</td>
|
||||
<td>
|
||||
<Address pubkey={spotMarketAccountMeta.pubkey} alignRight link />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Order type</td>
|
||||
<td className="text-lg-right">{info.orderType}</td>
|
||||
</tr>
|
||||
|
||||
{info.clientId !== "0" && (
|
||||
<tr>
|
||||
<td>Client Id</td>
|
||||
<td className="text-lg-right">{info.clientId}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
<tr>
|
||||
<td>Side</td>
|
||||
<td className="text-lg-right">{info.side}</td>
|
||||
</tr>
|
||||
|
||||
{orderLotDetails !== null && (
|
||||
<tr>
|
||||
<td>Limit price</td>
|
||||
{/* todo fix price */}
|
||||
<td className="text-lg-right">{orderLotDetails?.price} USDC</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
{orderLotDetails !== null && (
|
||||
<tr>
|
||||
<td>Size</td>
|
||||
<td className="text-lg-right">{orderLotDetails?.size}</td>
|
||||
</tr>
|
||||
)}
|
||||
</InstructionCard>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,430 @@
|
|||
import {
|
||||
Config,
|
||||
GroupConfig,
|
||||
MangoInstructionLayout,
|
||||
PerpMarket,
|
||||
PerpMarketConfig,
|
||||
PerpMarketLayout,
|
||||
SpotMarketConfig,
|
||||
} from "@blockworks-foundation/mango-client";
|
||||
import { Market } from "@project-serum/serum";
|
||||
import {
|
||||
AccountInfo,
|
||||
AccountMeta,
|
||||
Connection,
|
||||
PublicKey,
|
||||
TransactionInstruction,
|
||||
} from "@solana/web3.js";
|
||||
|
||||
// note: mainnet.1 suffices since its a superset of mainnet.0
|
||||
const mangoGroups = Config.ids().groups.filter(
|
||||
(group) => group.name !== "mainnet.0"
|
||||
);
|
||||
|
||||
// caching of account info's by public keys
|
||||
let accountInfoCache: Record<string, Promise<AccountInfo<Buffer> | null>> = {};
|
||||
function getAccountInfo(
|
||||
clusterUrl: string,
|
||||
publicKey: PublicKey
|
||||
): Promise<AccountInfo<Buffer> | null> {
|
||||
if (publicKey.toBase58() in accountInfoCache) {
|
||||
return accountInfoCache[publicKey.toBase58()];
|
||||
}
|
||||
const connection = new Connection(clusterUrl);
|
||||
const accountInfoPromise = connection.getAccountInfo(publicKey);
|
||||
accountInfoCache[publicKey.toBase58()] = accountInfoPromise;
|
||||
return accountInfoPromise;
|
||||
}
|
||||
|
||||
function findGroupConfig(programId: PublicKey): GroupConfig | undefined {
|
||||
const filtered = mangoGroups.filter((group) =>
|
||||
group.mangoProgramId.equals(programId)
|
||||
);
|
||||
if (filtered.length) {
|
||||
return filtered[0];
|
||||
}
|
||||
}
|
||||
|
||||
export const isMangoInstruction = (instruction: TransactionInstruction) => {
|
||||
return mangoGroups
|
||||
.map((group) => group.mangoProgramId.toBase58())
|
||||
.includes(instruction.programId.toBase58());
|
||||
};
|
||||
|
||||
export const INSTRUCTION_LOOKUP: { [key: number]: string } = {
|
||||
0: "InitMangoGroup",
|
||||
1: "InitMangoAccount",
|
||||
2: "Deposit",
|
||||
3: "Withdraw",
|
||||
4: "AddSpotMarket",
|
||||
5: "AddToBasket",
|
||||
6: "Borrow",
|
||||
7: "CachePrices",
|
||||
8: "CacheRootBanks",
|
||||
9: "PlaceSpotOrder",
|
||||
10: "AddOracle",
|
||||
11: "AddPerpMarket",
|
||||
12: "PlacePerpOrder",
|
||||
13: "CancelPerpOrderByClientId",
|
||||
14: "CancelPerpOrder",
|
||||
15: "ConsumeEvents",
|
||||
16: "CachePerpMarkets",
|
||||
17: "UpdateFunding",
|
||||
18: "SetOracle",
|
||||
19: "SettleFunds",
|
||||
20: "CancelSpotOrder",
|
||||
21: "UpdateRootBank",
|
||||
22: "SettlePnl",
|
||||
23: "SettleBorrow",
|
||||
24: "ForceCancelSpotOrders",
|
||||
25: "ForceCancelPerpOrders",
|
||||
26: "LiquidateTokenAndToken",
|
||||
27: "LiquidateTokenAndPerp",
|
||||
28: "LiquidatePerpMarket",
|
||||
29: "SettleFees",
|
||||
30: "ResolvePerpBankruptcy",
|
||||
31: "ResolveTokenBankruptcy",
|
||||
32: "InitSpotOpenOrders",
|
||||
33: "RedeemMngo",
|
||||
34: "AddMangoAccountInfo",
|
||||
35: "DepositMsrm",
|
||||
36: "WithdrawMsrm",
|
||||
37: "ChangePerpMarketParams",
|
||||
};
|
||||
|
||||
export const parseMangoInstructionTitle = (
|
||||
instruction: TransactionInstruction
|
||||
): string => {
|
||||
const code = instruction.data[0];
|
||||
|
||||
if (!(code in INSTRUCTION_LOOKUP)) {
|
||||
throw new Error(`Unrecognized Mango instruction code: ${code}`);
|
||||
}
|
||||
return INSTRUCTION_LOOKUP[code];
|
||||
};
|
||||
|
||||
export type Deposit = {
|
||||
quantity: number;
|
||||
};
|
||||
|
||||
export const decodeDeposit = (ix: TransactionInstruction): Deposit => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const deposit: Deposit = {
|
||||
quantity: decoded.Deposit.quantity.toNumber(),
|
||||
};
|
||||
return deposit;
|
||||
};
|
||||
|
||||
export type AddToBasket = {
|
||||
marketIndex: number;
|
||||
};
|
||||
|
||||
export const decodeAddToBasket = (ix: TransactionInstruction): AddToBasket => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const addToBasket: AddToBasket = {
|
||||
marketIndex: decoded.AddToBasket.marketIndex.toNumber(),
|
||||
};
|
||||
return addToBasket;
|
||||
};
|
||||
|
||||
export type Withdraw = {
|
||||
quantity: number;
|
||||
allowBorrow: String;
|
||||
};
|
||||
|
||||
export const decodeWithdraw = (ix: TransactionInstruction): Withdraw => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const withdraw: Withdraw = {
|
||||
quantity: decoded.Withdraw.quantity.toNumber(),
|
||||
allowBorrow: decoded.Withdraw.allowBorrow.toString(),
|
||||
};
|
||||
return withdraw;
|
||||
};
|
||||
|
||||
export type PlaceSpotOrder = {
|
||||
side: String;
|
||||
limitPrice: number;
|
||||
maxBaseQuantity: number;
|
||||
maxQuoteQuantity: number;
|
||||
selfTradeBehavior: String;
|
||||
orderType: String;
|
||||
clientId: String;
|
||||
limit: String;
|
||||
};
|
||||
|
||||
export const decodePlaceSpotOrder = (
|
||||
ix: TransactionInstruction
|
||||
): PlaceSpotOrder => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const placeSpotOrder: PlaceSpotOrder = {
|
||||
side: decoded.PlaceSpotOrder.side.toString(),
|
||||
limitPrice: decoded.PlaceSpotOrder.limitPrice.toNumber(),
|
||||
maxBaseQuantity: decoded.PlaceSpotOrder.maxBaseQuantity.toNumber(),
|
||||
maxQuoteQuantity: decoded.PlaceSpotOrder.maxQuoteQuantity.toNumber(),
|
||||
selfTradeBehavior: decoded.PlaceSpotOrder.selfTradeBehavior,
|
||||
orderType: decoded.PlaceSpotOrder.orderType.toString(),
|
||||
clientId: decoded.PlaceSpotOrder.clientId.toString(),
|
||||
limit: decoded.PlaceSpotOrder.limit.toString(),
|
||||
};
|
||||
|
||||
return placeSpotOrder;
|
||||
};
|
||||
|
||||
export type CancelSpotOrder = {
|
||||
orderId: String;
|
||||
side: String;
|
||||
};
|
||||
|
||||
export const decodeCancelSpotOrder = (
|
||||
ix: TransactionInstruction
|
||||
): CancelSpotOrder => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const cancelSpotOrder: CancelSpotOrder = {
|
||||
orderId: decoded.CancelSpotOrder.orderId.toString(),
|
||||
side: decoded.CancelSpotOrder.side.toString(),
|
||||
};
|
||||
return cancelSpotOrder;
|
||||
};
|
||||
|
||||
export type PlacePerpOrder = {
|
||||
price: number;
|
||||
quantity: number;
|
||||
clientOrderId: String;
|
||||
side: String;
|
||||
orderType: String;
|
||||
};
|
||||
export const decodePlacePerpOrder = (
|
||||
ix: TransactionInstruction
|
||||
): PlacePerpOrder => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const placePerpOrder: PlacePerpOrder = {
|
||||
price: decoded.PlacePerpOrder.price.toNumber(),
|
||||
quantity: decoded.PlacePerpOrder.quantity.toNumber(),
|
||||
clientOrderId: decoded.PlacePerpOrder.clientOrderId.toString(),
|
||||
side: decoded.PlacePerpOrder.side.toString(),
|
||||
orderType: decoded.PlacePerpOrder.orderType.toString(),
|
||||
};
|
||||
|
||||
return placePerpOrder;
|
||||
};
|
||||
|
||||
export type CancelPerpOrder = {
|
||||
orderId: String;
|
||||
invalidIdOk: String;
|
||||
};
|
||||
|
||||
export const decodeCancelPerpOrder = (
|
||||
ix: TransactionInstruction
|
||||
): CancelPerpOrder => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const cancelPerpOrder: CancelPerpOrder = {
|
||||
orderId: decoded.CancelPerpOrder.orderId.toString(),
|
||||
invalidIdOk: decoded.CancelPerpOrder.invalidIdOk.toString(),
|
||||
};
|
||||
return cancelPerpOrder;
|
||||
};
|
||||
|
||||
export type ChangePerpMarketParams = {
|
||||
maintLeverageOption: Boolean;
|
||||
maintLeverage: number;
|
||||
initLeverageOption: Boolean;
|
||||
initLeverage: number;
|
||||
liquidationFeeOption: Boolean;
|
||||
liquidationFee: number;
|
||||
makerFeeOption: Boolean;
|
||||
makerFee: number;
|
||||
takerFeeOption: Boolean;
|
||||
takerFee: number;
|
||||
rateOption: Boolean;
|
||||
rate: number;
|
||||
maxDepthBpsOption: Boolean;
|
||||
maxDepthBps: number;
|
||||
targetPeriodLengthOption: Boolean;
|
||||
targetPeriodLength: number;
|
||||
mngoPerPeriodOption: Boolean;
|
||||
mngoPerPeriod: number;
|
||||
};
|
||||
|
||||
export const decodeChangePerpMarketParams = (
|
||||
ix: TransactionInstruction
|
||||
): ChangePerpMarketParams => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const changePerpMarketParams: ChangePerpMarketParams = {
|
||||
maintLeverageOption: decoded.ChangePerpMarketParams.maintLeverageOption,
|
||||
maintLeverage: decoded.ChangePerpMarketParams.maintLeverage.toString(),
|
||||
initLeverageOption: decoded.ChangePerpMarketParams.initLeverageOption,
|
||||
initLeverage: decoded.ChangePerpMarketParams.initLeverage.toString(),
|
||||
liquidationFeeOption: decoded.ChangePerpMarketParams.liquidationFeeOption,
|
||||
liquidationFee: decoded.ChangePerpMarketParams.liquidationFee.toString(),
|
||||
makerFeeOption: decoded.ChangePerpMarketParams.makerFeeOption,
|
||||
makerFee: decoded.ChangePerpMarketParams.makerFee.toString(),
|
||||
takerFeeOption: decoded.ChangePerpMarketParams.takerFeeOption,
|
||||
takerFee: decoded.ChangePerpMarketParams.takerFee.toString(),
|
||||
rateOption: decoded.ChangePerpMarketParams.rateOption,
|
||||
rate: decoded.ChangePerpMarketParams.rate.toString(),
|
||||
maxDepthBpsOption: decoded.ChangePerpMarketParams.maxDepthBpsOption,
|
||||
maxDepthBps: decoded.ChangePerpMarketParams.maxDepthBps.toString(),
|
||||
targetPeriodLengthOption:
|
||||
decoded.ChangePerpMarketParams.targetPeriodLengthOption,
|
||||
targetPeriodLength:
|
||||
decoded.ChangePerpMarketParams.targetPeriodLength.toString(),
|
||||
mngoPerPeriodOption: decoded.ChangePerpMarketParams.mngoPerPeriodOption,
|
||||
mngoPerPeriod: decoded.ChangePerpMarketParams.mngoPerPeriod.toString(),
|
||||
};
|
||||
return changePerpMarketParams;
|
||||
};
|
||||
|
||||
export type AddSpotMarket = {
|
||||
marketIndex: number;
|
||||
maintLeverage: number;
|
||||
initLeverage: number;
|
||||
liquidationFee: number;
|
||||
optimalUtil: number;
|
||||
optimalRate: number;
|
||||
maxRate: number;
|
||||
};
|
||||
|
||||
export const decodeAddSpotMarket = (
|
||||
ix: TransactionInstruction
|
||||
): AddSpotMarket => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const addSpotMarket: AddSpotMarket = {
|
||||
marketIndex: decoded.AddSpotMarket.marketIndex.toNumber(),
|
||||
maintLeverage: decoded.AddSpotMarket.maintLeverage.toNumber(),
|
||||
initLeverage: decoded.AddSpotMarket.initLeverage.toNumber(),
|
||||
liquidationFee: decoded.AddSpotMarket.liquidationFee.toNumber(),
|
||||
optimalUtil: decoded.AddSpotMarket.optimalUtil.toNumber(),
|
||||
optimalRate: decoded.AddSpotMarket.optimalRate.toNumber(),
|
||||
maxRate: decoded.AddSpotMarket.maxRate.toNumber(),
|
||||
};
|
||||
return addSpotMarket;
|
||||
};
|
||||
|
||||
export type AddPerpMarket = {
|
||||
marketIndex: number;
|
||||
maintLeverage: number;
|
||||
initLeverage: number;
|
||||
liquidationFee: number;
|
||||
makerFee: number;
|
||||
takerFee: number;
|
||||
baseLotSize: number;
|
||||
quoteLotSize: number;
|
||||
rate: number;
|
||||
maxDepthBps: number;
|
||||
targetPeriodLength: number;
|
||||
mngoPerPeriod: number;
|
||||
};
|
||||
|
||||
export const decodeAddPerpMarket = (
|
||||
ix: TransactionInstruction
|
||||
): AddPerpMarket => {
|
||||
const decoded = MangoInstructionLayout.decode(ix.data);
|
||||
const addPerpMarket: AddPerpMarket = {
|
||||
marketIndex: decoded.AddPerpMarket.marketIndex.toNumber(),
|
||||
maintLeverage: decoded.AddPerpMarket.maintLeverage.toNumber(),
|
||||
initLeverage: decoded.AddPerpMarket.initLeverage.toNumber(),
|
||||
liquidationFee: decoded.AddPerpMarket.liquidationFee.toNumber(),
|
||||
makerFee: decoded.AddPerpMarket.makerFee.toNumber(),
|
||||
takerFee: decoded.AddPerpMarket.takerFee.toNumber(),
|
||||
baseLotSize: decoded.AddPerpMarket.baseLotSize.toNumber(),
|
||||
quoteLotSize: decoded.AddPerpMarket.quoteLotSize.toNumber(),
|
||||
rate: decoded.AddPerpMarket.rate.toNumber(),
|
||||
maxDepthBps: decoded.AddPerpMarket.maxDepthBps.toNumber(),
|
||||
targetPeriodLength: decoded.AddPerpMarket.targetPeriodLength.toNumber(),
|
||||
mngoPerPeriod: decoded.AddPerpMarket.mngoPerPeriod.toNumber(),
|
||||
};
|
||||
return addPerpMarket;
|
||||
};
|
||||
|
||||
export type OrderLotDetails = {
|
||||
price: number;
|
||||
size: number;
|
||||
};
|
||||
|
||||
////
|
||||
|
||||
export function logAllKeys(keys: AccountMeta[]) {
|
||||
keys.map((key) => console.log(key.pubkey.toBase58()));
|
||||
}
|
||||
|
||||
export function getSpotMarketFromInstruction(
|
||||
ix: TransactionInstruction,
|
||||
spotMarket: AccountMeta
|
||||
): SpotMarketConfig | undefined {
|
||||
const groupConfig = findGroupConfig(ix.programId);
|
||||
if (groupConfig === undefined) {
|
||||
return;
|
||||
}
|
||||
const spotMarketConfigs = groupConfig.spotMarkets.filter((mangoSpotMarket) =>
|
||||
spotMarket.pubkey.equals(mangoSpotMarket.publicKey)
|
||||
);
|
||||
if (spotMarketConfigs.length) {
|
||||
return spotMarketConfigs[0];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSpotMarketFromSpotMarketConfig(
|
||||
programId: PublicKey,
|
||||
clusterUrl: string,
|
||||
mangoSpotMarketConfig: SpotMarketConfig
|
||||
): Promise<Market | undefined> {
|
||||
const connection = new Connection(clusterUrl);
|
||||
const groupConfig = findGroupConfig(programId);
|
||||
if (groupConfig === undefined) {
|
||||
return;
|
||||
}
|
||||
return await Market.load(
|
||||
connection,
|
||||
mangoSpotMarketConfig.publicKey,
|
||||
undefined,
|
||||
groupConfig.serumProgramId
|
||||
);
|
||||
}
|
||||
|
||||
export function getPerpMarketFromInstruction(
|
||||
ix: TransactionInstruction,
|
||||
perpMarket: AccountMeta
|
||||
): PerpMarketConfig | undefined {
|
||||
const groupConfig = findGroupConfig(ix.programId);
|
||||
if (groupConfig === undefined) {
|
||||
return;
|
||||
}
|
||||
const perpMarketConfigs = groupConfig.perpMarkets.filter((mangoPerpMarket) =>
|
||||
perpMarket.pubkey.equals(mangoPerpMarket.publicKey)
|
||||
);
|
||||
if (perpMarketConfigs.length) {
|
||||
return perpMarketConfigs[0];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPerpMarketFromPerpMarketConfig(
|
||||
clusterUrl: string,
|
||||
mangoPerpMarketConfig: PerpMarketConfig
|
||||
): Promise<PerpMarket> {
|
||||
const acc = await getAccountInfo(clusterUrl, mangoPerpMarketConfig.publicKey);
|
||||
const decoded = PerpMarketLayout.decode(acc?.data);
|
||||
|
||||
return new PerpMarket(
|
||||
mangoPerpMarketConfig.publicKey,
|
||||
mangoPerpMarketConfig.baseDecimals,
|
||||
mangoPerpMarketConfig.quoteDecimals,
|
||||
decoded
|
||||
);
|
||||
}
|
||||
|
||||
export function spotMarketFromIndex(
|
||||
ix: TransactionInstruction,
|
||||
marketIndex: number
|
||||
): String | undefined {
|
||||
const groupConfig = findGroupConfig(ix.programId);
|
||||
if (groupConfig === undefined) {
|
||||
return;
|
||||
}
|
||||
const spotMarketConfigs = groupConfig.spotMarkets.filter(
|
||||
(spotMarketConfig) => spotMarketConfig.marketIndex === marketIndex
|
||||
);
|
||||
if (!spotMarketConfigs.length) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return spotMarketConfigs[0].name;
|
||||
}
|
|
@ -39,6 +39,8 @@ import { BpfUpgradeableLoaderDetailsCard } from "components/instruction/bpf-upgr
|
|||
import { VoteDetailsCard } from "components/instruction/vote/VoteDetailsCard";
|
||||
import { isWormholeInstruction } from "components/instruction/wormhole/types";
|
||||
import { AssociatedTokenDetailsCard } from "components/instruction/AssociatedTokenDetailsCard";
|
||||
import { isMangoInstruction } from "components/instruction/mango/types";
|
||||
import { MangoDetailsCard } from "components/instruction/MangoDetails";
|
||||
|
||||
export type InstructionDetailsProps = {
|
||||
tx: ParsedTransaction;
|
||||
|
@ -208,6 +210,8 @@ function renderInstructionCard({
|
|||
|
||||
if (isBonfidaBotInstruction(transactionIx)) {
|
||||
return <BonfidaBotDetailsCard key={key} {...props} />;
|
||||
} else if (isMangoInstruction(transactionIx)) {
|
||||
return <MangoDetailsCard key={key} {...props} />;
|
||||
} else if (isSerumInstruction(transactionIx)) {
|
||||
return <SerumDetailsCard key={key} {...props} />;
|
||||
} else if (isTokenSwapInstruction(transactionIx)) {
|
||||
|
|
|
@ -50,6 +50,7 @@ export enum PROGRAM_NAMES {
|
|||
SERUM_1 = "Serum Program v1",
|
||||
SERUM_2 = "Serum Program v2",
|
||||
SERUM_3 = "Serum Program v3",
|
||||
MANGO_3 = "Mango Program v3",
|
||||
}
|
||||
|
||||
const ALL_CLUSTERS = [
|
||||
|
@ -90,6 +91,7 @@ export const PROGRAM_DEPLOYMENTS = {
|
|||
[PROGRAM_NAMES.SERUM_1]: MAINNET_ONLY,
|
||||
[PROGRAM_NAMES.SERUM_2]: MAINNET_ONLY,
|
||||
[PROGRAM_NAMES.SERUM_3]: MAINNET_ONLY,
|
||||
[PROGRAM_NAMES.MANGO_3]: MAINNET_ONLY,
|
||||
} as const;
|
||||
|
||||
export const PROGRAM_NAME_BY_ID = {
|
||||
|
@ -121,6 +123,7 @@ export const PROGRAM_NAME_BY_ID = {
|
|||
BJ3jrUzddfuSrZHXSCxMUUQsjKEyLmuuyZebkcaFp2fg: PROGRAM_NAMES.SERUM_1,
|
||||
EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o: PROGRAM_NAMES.SERUM_2,
|
||||
"9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin": PROGRAM_NAMES.SERUM_3,
|
||||
mv3ekLzLbnVPNxjSKvqBpU3ZeZXPQdEC3bp5MDEBG68: PROGRAM_NAMES.MANGO_3,
|
||||
} as const;
|
||||
|
||||
export type LoaderName = typeof LOADER_IDS[keyof typeof LOADER_IDS];
|
||||
|
|
Loading…
Reference in New Issue