explorer: add Pyth instruction support (#23551)

This commit is contained in:
Richard Patel 2022-03-11 14:59:16 +01:00 committed by GitHub
parent 9b591286d7
commit 3d021cffa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1547 additions and 112 deletions

View File

@ -17,6 +17,7 @@
"@project-serum/serum": "^0.13.61",
"@react-hook/debounce": "^4.0.0",
"@sentry/react": "^6.16.1",
"@solana/buffer-layout": "^3.0.0",
"@solana/spl-token-registry": "^0.2.1143",
"@solana/web3.js": "^1.31.0",
"@testing-library/jest-dom": "^5.16.1",
@ -10297,24 +10298,30 @@
}
},
"node_modules/es-abstract": {
"version": "1.18.0-next.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz",
"integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==",
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
"integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
"dependencies": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2",
"get-intrinsic": "^1.1.1",
"get-symbol-description": "^1.0.0",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"has-symbols": "^1.0.2",
"internal-slot": "^1.0.3",
"is-callable": "^1.2.4",
"is-negative-zero": "^2.0.1",
"is-regex": "^1.1.1",
"object-inspect": "^1.9.0",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.1",
"is-string": "^1.0.7",
"is-weakref": "^1.0.1",
"object-inspect": "^1.11.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
"string.prototype.trimend": "^1.0.3",
"string.prototype.trimstart": "^1.0.3"
"string.prototype.trimend": "^1.0.4",
"string.prototype.trimstart": "^1.0.4",
"unbox-primitive": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
@ -12526,6 +12533,21 @@
"node": ">=6"
}
},
"node_modules/get-symbol-description": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@ -12696,6 +12718,14 @@
"node": ">= 0.4.0"
}
},
"node_modules/has-bigints": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
@ -12710,9 +12740,23 @@
}
},
"node_modules/has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dependencies": {
"has-symbols": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
@ -13556,6 +13600,17 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"node_modules/is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dependencies": {
"has-bigints": "^1.0.1"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@ -13567,15 +13622,30 @@
"node": ">=8"
}
},
"node_modules/is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"node_modules/is-callable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
"integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==",
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
"engines": {
"node": ">= 0.4"
},
@ -13763,6 +13833,20 @@
"node": ">=0.12.0"
}
},
"node_modules/is-number-object": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
"integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
"dependencies": {
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-obj": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
@ -13826,11 +13910,12 @@
"integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c="
},
"node_modules/is-regex": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
"integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"dependencies": {
"has-symbols": "^1.0.1"
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@ -13860,6 +13945,14 @@
"node": ">=6"
}
},
"node_modules/is-shared-array-buffer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
"integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
@ -13869,9 +13962,12 @@
}
},
"node_modules/is-string": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"dependencies": {
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
@ -13898,6 +13994,17 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"node_modules/is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dependencies": {
"call-bind": "^1.0.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@ -19001,9 +19108,9 @@
}
},
"node_modules/object-inspect": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
"integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==",
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
"integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -23864,11 +23971,11 @@
}
},
"node_modules/string.prototype.trimend": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz",
"integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
"dependencies": {
"call-bind": "^1.0.0",
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
},
"funding": {
@ -23876,11 +23983,11 @@
}
},
"node_modules/string.prototype.trimstart": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz",
"integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
"dependencies": {
"call-bind": "^1.0.0",
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
},
"funding": {
@ -24924,6 +25031,20 @@
"node": "*"
}
},
"node_modules/unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
"dependencies": {
"function-bind": "^1.1.1",
"has-bigints": "^1.0.1",
"has-symbols": "^1.0.2",
"which-boxed-primitive": "^1.0.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
@ -25259,30 +25380,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/util.promisify/node_modules/es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"dependencies": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/util/node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
@ -26604,6 +26701,21 @@
"which": "bin/which"
}
},
"node_modules/which-boxed-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"dependencies": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
"is-number-object": "^1.0.4",
"is-string": "^1.0.5",
"is-symbol": "^1.0.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
@ -35124,24 +35236,30 @@
}
},
"es-abstract": {
"version": "1.18.0-next.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz",
"integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==",
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
"integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2",
"get-intrinsic": "^1.1.1",
"get-symbol-description": "^1.0.0",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"has-symbols": "^1.0.2",
"internal-slot": "^1.0.3",
"is-callable": "^1.2.4",
"is-negative-zero": "^2.0.1",
"is-regex": "^1.1.1",
"object-inspect": "^1.9.0",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.1",
"is-string": "^1.0.7",
"is-weakref": "^1.0.1",
"object-inspect": "^1.11.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
"string.prototype.trimend": "^1.0.3",
"string.prototype.trimstart": "^1.0.3"
"string.prototype.trimend": "^1.0.4",
"string.prototype.trimstart": "^1.0.4",
"unbox-primitive": "^1.0.1"
}
},
"es-to-primitive": {
@ -36818,6 +36936,15 @@
"pump": "^3.0.0"
}
},
"get-symbol-description": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"requires": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1"
}
},
"get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@ -36947,6 +37074,11 @@
"function-bind": "^1.1.1"
}
},
"has-bigints": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
},
"has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
@ -36958,9 +37090,17 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
},
"has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"requires": {
"has-symbols": "^1.0.2"
}
},
"has-value": {
"version": "1.0.0",
@ -37637,6 +37777,14 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"requires": {
"has-bigints": "^1.0.1"
}
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@ -37645,15 +37793,24 @@
"binary-extensions": "^2.0.0"
}
},
"is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-callable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
"integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA=="
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w=="
},
"is-capitalized": {
"version": "1.0.0",
@ -37782,6 +37939,14 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"is-number-object": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
"integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
"requires": {
"has-tostringtag": "^1.0.0"
}
},
"is-obj": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
@ -37827,11 +37992,12 @@
"integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c="
},
"is-regex": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
"integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"requires": {
"has-symbols": "^1.0.1"
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-regexp": {
@ -37849,15 +38015,23 @@
"resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz",
"integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg=="
},
"is-shared-array-buffer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
"integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA=="
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"is-string": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ=="
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"requires": {
"has-tostringtag": "^1.0.0"
}
},
"is-symbol": {
"version": "1.0.3",
@ -37872,6 +38046,14 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"requires": {
"call-bind": "^1.0.2"
}
},
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@ -41775,9 +41957,9 @@
}
},
"object-inspect": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
"integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw=="
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
"integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
},
"object-is": {
"version": "1.1.5",
@ -45657,20 +45839,20 @@
}
},
"string.prototype.trimend": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz",
"integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
"requires": {
"call-bind": "^1.0.0",
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
"string.prototype.trimstart": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz",
"integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
"requires": {
"call-bind": "^1.0.0",
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
@ -46462,6 +46644,17 @@
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.28.tgz",
"integrity": "sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g=="
},
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
"requires": {
"function-bind": "^1.1.1",
"has-bigints": "^1.0.1",
"has-symbols": "^1.0.2",
"which-boxed-primitive": "^1.0.2"
}
},
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
@ -46717,26 +46910,6 @@
"es-abstract": "^1.17.2",
"has-symbols": "^1.0.1",
"object.getownpropertydescriptors": "^2.1.0"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
}
}
},
"utila": {
@ -47807,6 +47980,18 @@
"isexe": "^2.0.0"
}
},
"which-boxed-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"requires": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
"is-number-object": "^1.0.4",
"is-string": "^1.0.5",
"is-symbol": "^1.0.3"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",

View File

@ -12,6 +12,7 @@
"@project-serum/serum": "^0.13.61",
"@react-hook/debounce": "^4.0.0",
"@sentry/react": "^6.16.1",
"@solana/buffer-layout": "^3.0.0",
"@solana/spl-token-registry": "^0.2.1143",
"@solana/web3.js": "^1.31.0",
"@testing-library/jest-dom": "^5.16.1",

View File

@ -0,0 +1,60 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { AddMappingParams } from "./program";
export default function AddMappingDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: AddMappingParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Add Mapping Account"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Mapping Account</td>
<td className="text-lg-end">
<Address pubkey={info.mappingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Next Mapping Account</td>
<td className="text-lg-end">
<Address pubkey={info.nextMappingPubkey} alignRight link />
</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,70 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { AddPriceParams, PriceType } from "./program";
export default function AddPriceDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: AddPriceParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Add Price Account"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Product Account</td>
<td className="text-lg-end">
<Address pubkey={info.productPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Price Account</td>
<td className="text-lg-end">
<Address pubkey={info.pricePubkey} alignRight link />
</td>
</tr>
<tr>
<td>Exponent</td>
<td className="text-lg-end">{info.exponent}</td>
</tr>
<tr>
<td>Price Type</td>
<td className="text-lg-end">{PriceType[info.priceType]}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,60 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { AddProductParams } from "./program";
export default function AddProductDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: AddProductParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Add Product"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Mapping Account</td>
<td className="text-lg-end">
<Address pubkey={info.mappingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Product Account</td>
<td className="text-lg-end">
<Address pubkey={info.productPubkey} alignRight link />
</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,53 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { AggregatePriceParams } from "./program";
export default function AggregatePriceDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: AggregatePriceParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Update Price"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Price Account</td>
<td className="text-lg-end">
<Address pubkey={info.pricePubkey} alignRight link />
</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,55 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { BasePublisherOperationParams } from "./program";
export default function BasePublisherOperationCard({
ix,
index,
result,
operationName,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
operationName: string;
info: BasePublisherOperationParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title={`Pyth: ${operationName}`}
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Price Account</td>
<td className="text-lg-end">
<Address pubkey={info.pricePubkey} alignRight link />
</td>
</tr>
<tr>
<td>Publisher</td>
<td className="text-lg-end">
<Address pubkey={info.publisherPubkey} alignRight link />
</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,53 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { InitMappingParams } from "./program";
export default function InitMappingDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: InitMappingParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Init Mapping Account"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Mapping Account</td>
<td className="text-lg-end">
<Address pubkey={info.mappingPubkey} alignRight link />
</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,63 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { InitPriceParams, PriceType } from "./program";
export default function InitPriceDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: InitPriceParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Init Price Account"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Price Account</td>
<td className="text-lg-end">
<Address pubkey={info.pricePubkey} alignRight link />
</td>
</tr>
<tr>
<td>Exponent</td>
<td className="text-lg-end">{info.exponent}</td>
</tr>
<tr>
<td>Price Type</td>
<td className="text-lg-end">{PriceType[info.priceType]}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,123 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { useCluster } from "providers/cluster";
import { reportError } from "utils/sentry";
import { InstructionCard } from "../InstructionCard";
import { PythInstruction } from "./program";
import UpdatePriceDetailsCard from "./UpdatePriceDetailsCard";
import BasePublisherOperationCard from "./BasePublisherOperationCard";
import AddProductDetailsCard from "./AddProductDetailsCard";
import AddPriceDetailsCard from "./AddPriceDetailsCard";
import UpdateProductDetailsCard from "./UpdateProductDetailsCard";
import InitMappingDetailsCard from "./InitMappingDetailsCard";
import AddMappingDetailsCard from "./AddMappingDetailsCard";
import AggregatePriceDetailsCard from "./AggregatePriceDetailsCard";
import InitPriceDetailsCard from "./InitPriceDetailsCard";
export function PythDetailsCard(props: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
signature: string;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const { url } = useCluster();
const { ix, index, result, signature, innerCards, childIndex } = props;
try {
let ixType = PythInstruction.decodeInstructionType(ix);
switch (ixType) {
case "InitMapping":
return (
<InitMappingDetailsCard
info={PythInstruction.decodeInitMapping(ix)}
{...props}
/>
);
case "AddMapping":
return (
<AddMappingDetailsCard
info={PythInstruction.decodeAddMapping(ix)}
{...props}
/>
);
case "AddProduct":
return (
<AddProductDetailsCard
info={PythInstruction.decodeAddProduct(ix)}
{...props}
/>
);
case "UpdateProduct":
return (
<UpdateProductDetailsCard
info={PythInstruction.decodeUpdateProduct(ix)}
{...props}
/>
);
case "AddPrice":
return (
<AddPriceDetailsCard
info={PythInstruction.decodeAddPrice(ix)}
{...props}
/>
);
case "AddPublisher":
return (
<BasePublisherOperationCard
operationName="Add Publisher"
info={PythInstruction.decodeAddPublisher(ix)}
{...props}
/>
);
case "DeletePublisher":
return (
<BasePublisherOperationCard
operationName="Delete Publisher"
info={PythInstruction.decodeDeletePublisher(ix)}
{...props}
/>
);
case "UpdatePrice":
return (
<UpdatePriceDetailsCard
info={PythInstruction.decodeUpdatePrice(ix)}
{...props}
/>
);
case "AggregatePrice":
return (
<AggregatePriceDetailsCard
info={PythInstruction.decodeAggregatePrice(ix)}
{...props}
/>
);
case "InitPrice":
return (
<InitPriceDetailsCard
info={PythInstruction.decodeInitPrice(ix)}
{...props}
/>
);
}
} catch (error) {
reportError(error, {
url: url,
signature: signature,
});
}
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title={`Pyth: Unknown`}
innerCards={innerCards}
childIndex={childIndex}
defaultRaw
/>
);
}

View File

@ -0,0 +1,58 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { SetMinPublishersParams } from "./program";
export default function SetMinPublishersDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: SetMinPublishersParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Set Minimum Number Of Publishers"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Price Account</td>
<td className="text-lg-end">
<Address pubkey={info.pricePubkey} alignRight link />
</td>
</tr>
<tr>
<td>Min Publishers</td>
<td className="text-lg-end">{info.minPublishers}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,73 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { InstructionCard } from "../InstructionCard";
import { TradingStatus, UpdatePriceParams } from "./program";
export default function UpdatePriceDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: UpdatePriceParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Update Price"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Publisher</td>
<td className="text-lg-end">
<Address pubkey={info.publisherPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Price Account</td>
<td className="text-lg-end">
<Address pubkey={info.pricePubkey} alignRight link />
</td>
</tr>
<tr>
<td>Status</td>
<td className="text-lg-end">{TradingStatus[info.status]}</td>
</tr>
<tr>
<td>Price</td>
<td className="text-lg-end">{info.price}</td>
</tr>
<tr>
<td>Conf</td>
<td className="text-lg-end">{info.conf}</td>
</tr>
<tr>
<td>Publish Slot</td>
<td className="text-lg-end">{info.publishSlot}</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,82 @@
import React from "react";
import { SignatureResult, TransactionInstruction } from "@solana/web3.js";
import { Address } from "components/common/Address";
import { Copyable } from "components/common/Copyable";
import { InstructionCard } from "../InstructionCard";
import { UpdateProductParams } from "./program";
export default function UpdateProductDetailsCard({
ix,
index,
result,
info,
innerCards,
childIndex,
}: {
ix: TransactionInstruction;
index: number;
result: SignatureResult;
info: UpdateProductParams;
innerCards?: JSX.Element[];
childIndex?: number;
}) {
const attrsJSON = JSON.stringify(
Object.fromEntries(info.attributes),
null,
2
);
function Content() {
return (
<Copyable text={attrsJSON}>
<pre className="d-inline-block text-start mb-0">{attrsJSON}</pre>
</Copyable>
);
}
return (
<InstructionCard
ix={ix}
index={index}
result={result}
title="Pyth: Update Product"
innerCards={innerCards}
childIndex={childIndex}
>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={ix.programId} alignRight link />
</td>
</tr>
<tr>
<td>Funding Account</td>
<td className="text-lg-end">
<Address pubkey={info.fundingPubkey} alignRight link />
</td>
</tr>
<tr>
<td>Product Account</td>
<td className="text-lg-end">
<Address pubkey={info.productPubkey} alignRight link />
</td>
</tr>
<tr>
<td>
Attributes <span className="text-muted">(JSON)</span>
</td>
<td className="text-lg-end">
<div className="d-none d-lg-flex align-items-center justify-content-end">
<Content />
</div>
<div className="d-flex d-lg-none align-items-center">
<Content />
</div>
</td>
</tr>
</InstructionCard>
);
}

View File

@ -0,0 +1,482 @@
import * as BufferLayout from "@solana/buffer-layout";
import {
InstructionType,
PublicKey,
TransactionInstruction,
} from "@solana/web3.js";
import { Layout, uint8ArrayToBuffer } from "@solana/buffer-layout";
/**
* An enumeration of valid PythInstructionTypes
*/
export type PythInstructionType =
| "InitMapping"
| "AddMapping"
| "AddProduct"
| "UpdateProduct"
| "AddPrice"
| "AddPublisher"
| "DeletePublisher"
| "UpdatePrice"
| "AggregatePrice"
| "InitPrice"
| "InitTest"
| "UpdateTest"
| "SetMinPublishers";
export function headerLayout(property: string = "header") {
return BufferLayout.struct(
[BufferLayout.u32("version"), BufferLayout.u32("type")],
property
);
}
function decodeData(type: InstructionType, buffer: Buffer): any {
let data;
try {
data = type.layout.decode(buffer);
} catch (err) {
throw new Error("invalid instruction; " + err);
}
if (data.header.type !== type.index) {
throw new Error(
`invalid instruction; instruction index mismatch ${data.header.type} != ${type.index}`
);
}
return data;
}
/**
* An uint8 length-prefixed UTF-8 string.
*/
class LPString extends Layout {
getSpan(b: Uint8Array, offset?: number): number {
return 1 + b[offset || 0];
}
decode(b: Uint8Array, offset?: number): string {
if (offset === undefined) {
offset = 0;
}
return uint8ArrayToBuffer(b)
.slice(offset + 1, offset + b[offset] + 1)
.toString("utf-8");
}
}
/**
* A list that fills up all the available space with its elements.
*/
class GreedyList extends Layout {
private element: Layout;
constructor(element: Layout, property?: string) {
super(-1, property);
this.element = element;
}
getSpan(b: Uint8Array, offset?: number): number {
return b.length - (offset || 0);
}
decode(b: Uint8Array, offset?: number): string[] {
if (offset === undefined) {
offset = 0;
}
const strs = [];
while (offset < b.length) {
strs.push(this.element.decode(b, offset));
offset += this.element.getSpan(b, offset);
}
return strs;
}
}
/**
* An enumeration of valid Pyth instruction layouts
* @internal
*/
export const PYTH_INSTRUCTION_LAYOUTS: {
[type in PythInstructionType]: InstructionType;
} = Object.freeze({
InitMapping: {
index: 0,
layout: BufferLayout.struct([headerLayout()]),
},
AddMapping: {
index: 1,
layout: BufferLayout.struct([headerLayout()]),
},
AddProduct: {
index: 2,
layout: BufferLayout.struct([headerLayout()]),
},
UpdateProduct: {
index: 3,
layout: BufferLayout.struct([
headerLayout(),
new GreedyList(
BufferLayout.struct([
new LPString(-1, "key"),
new LPString(-1, "value"),
]),
"attributes"
),
]),
},
AddPrice: {
index: 4,
layout: BufferLayout.struct([
headerLayout(),
BufferLayout.s32("exponent"),
BufferLayout.u32("priceType"),
]),
},
AddPublisher: {
index: 5,
layout: BufferLayout.struct([
headerLayout(),
BufferLayout.blob(32, "publisherPubkey"),
]),
},
DeletePublisher: {
index: 6,
layout: BufferLayout.struct([
headerLayout(),
BufferLayout.blob(32, "publisherPubkey"),
]),
},
UpdatePrice: {
index: 7,
layout: BufferLayout.struct([
headerLayout(),
BufferLayout.u32("status"),
BufferLayout.u32("unused1"),
BufferLayout.ns64("price"),
BufferLayout.nu64("conf"),
BufferLayout.nu64("publishSlot"),
]),
},
AggregatePrice: {
index: 8,
layout: BufferLayout.struct([headerLayout()]),
},
InitPrice: {
index: 9,
layout: BufferLayout.struct([
headerLayout(),
BufferLayout.s32("exponent"),
BufferLayout.u32("priceType"),
]),
},
InitTest: {
index: 10,
layout: BufferLayout.struct([headerLayout()]),
},
UpdateTest: {
index: 11,
layout: BufferLayout.struct([headerLayout()]),
},
SetMinPublishers: {
index: 12,
layout: BufferLayout.struct([
headerLayout(),
BufferLayout.u8("minPublishers"),
BufferLayout.blob(3, "unused1"),
]),
},
});
export enum PriceType {
Unknown = 0,
Price,
}
export enum TradingStatus {
Unknown = 0,
Trading,
Halted,
Auction,
}
export type InitMappingParams = {
fundingPubkey: PublicKey;
mappingPubkey: PublicKey;
};
export type AddMappingParams = {
fundingPubkey: PublicKey;
mappingPubkey: PublicKey;
nextMappingPubkey: PublicKey;
};
export type AddProductParams = {
fundingPubkey: PublicKey;
mappingPubkey: PublicKey;
productPubkey: PublicKey;
};
export type UpdateProductParams = {
fundingPubkey: PublicKey;
productPubkey: PublicKey;
attributes: Map<String, String>;
};
export type AddPriceParams = {
fundingPubkey: PublicKey;
productPubkey: PublicKey;
pricePubkey: PublicKey;
exponent: number;
priceType: PriceType;
};
export type BasePublisherOperationParams = {
signerPubkey: PublicKey;
pricePubkey: PublicKey;
publisherPubkey: PublicKey;
};
export type UpdatePriceParams = {
publisherPubkey: PublicKey;
pricePubkey: PublicKey;
status: TradingStatus;
price: number;
conf: number;
publishSlot: number;
};
export type AggregatePriceParams = {
fundingPubkey: PublicKey;
pricePubkey: PublicKey;
};
export type InitPriceParams = {
fundingPubkey: PublicKey;
pricePubkey: PublicKey;
exponent: number;
priceType: PriceType;
};
export type SetMinPublishersParams = {
fundingPubkey: PublicKey;
pricePubkey: PublicKey;
minPublishers: number;
};
/**
* Pyth Instruction class
*/
export class PythInstruction {
/**
* Decode a Pyth instruction and retrieve the instruction type.
*/
static decodeInstructionType(
instruction: TransactionInstruction
): PythInstructionType {
const header = headerLayout().decode(instruction.data);
if (header.version !== 2) {
throw new Error(`Unsupported Pyth version: ${header.version}`);
}
const typeIndex = header.type;
let type: PythInstructionType | undefined;
for (const [ixType, layout] of Object.entries(PYTH_INSTRUCTION_LAYOUTS)) {
if (layout.index === typeIndex) {
type = ixType as PythInstructionType;
break;
}
}
if (!type) {
throw new Error("Instruction type incorrect; not a PythInstruction");
}
return type;
}
/**
* Decode an "init mapping" instruction and retrieve the instruction params.
*/
static decodeInitMapping(
instruction: TransactionInstruction
): InitMappingParams {
decodeData(PYTH_INSTRUCTION_LAYOUTS.InitMapping, instruction.data);
return {
fundingPubkey: instruction.keys[0].pubkey,
mappingPubkey: instruction.keys[1].pubkey,
};
}
/**
* Decode an "add mapping" instruction and retrieve the instruction params.
*/
static decodeAddMapping(
instruction: TransactionInstruction
): AddMappingParams {
decodeData(PYTH_INSTRUCTION_LAYOUTS.AddMapping, instruction.data);
return {
fundingPubkey: instruction.keys[0].pubkey,
mappingPubkey: instruction.keys[1].pubkey,
nextMappingPubkey: instruction.keys[2].pubkey,
};
}
/**
* Decode an "add product" instruction and retrieve the instruction params.
*/
static decodeAddProduct(
instruction: TransactionInstruction
): AddProductParams {
decodeData(PYTH_INSTRUCTION_LAYOUTS.AddProduct, instruction.data);
return {
fundingPubkey: instruction.keys[0].pubkey,
mappingPubkey: instruction.keys[1].pubkey,
productPubkey: instruction.keys[2].pubkey,
};
}
/**
* Decode an "add product" instruction and retrieve the instruction params.
*/
static decodeUpdateProduct(
instruction: TransactionInstruction
): UpdateProductParams {
const { attributes } = decodeData(
PYTH_INSTRUCTION_LAYOUTS.UpdateProduct,
instruction.data
);
return {
fundingPubkey: instruction.keys[0].pubkey,
productPubkey: instruction.keys[1].pubkey,
attributes: new Map(
attributes.map((kv: { key: string; value: string }) => [
kv.key,
kv.value,
])
),
};
}
/**
* Decode an "add price" instruction and retrieve the instruction params.
*/
static decodeAddPrice(instruction: TransactionInstruction): AddPriceParams {
const { exponent, priceType } = decodeData(
PYTH_INSTRUCTION_LAYOUTS.AddPrice,
instruction.data
);
return {
fundingPubkey: instruction.keys[0].pubkey,
productPubkey: instruction.keys[1].pubkey,
pricePubkey: instruction.keys[2].pubkey,
exponent,
priceType,
};
}
/**
* Decode an "add publisher" instruction and retrieve the instruction params.
*/
static decodeAddPublisher(
instruction: TransactionInstruction
): BasePublisherOperationParams {
const { publisherPubkey } = decodeData(
PYTH_INSTRUCTION_LAYOUTS.AddPublisher,
instruction.data
);
return {
signerPubkey: instruction.keys[0].pubkey,
pricePubkey: instruction.keys[1].pubkey,
publisherPubkey: PublicKey.decode(publisherPubkey),
};
}
/**
* Decode an "delete publisher" instruction and retrieve the instruction params.
*/
static decodeDeletePublisher(
instruction: TransactionInstruction
): BasePublisherOperationParams {
const { publisherPubkey } = decodeData(
PYTH_INSTRUCTION_LAYOUTS.DeletePublisher,
instruction.data
);
return {
signerPubkey: instruction.keys[0].pubkey,
pricePubkey: instruction.keys[1].pubkey,
publisherPubkey: PublicKey.decode(publisherPubkey),
};
}
/**
* Decode an "update price" instruction and retrieve the instruction params.
*/
static decodeUpdatePrice(
instruction: TransactionInstruction
): UpdatePriceParams {
const { status, price, conf, publishSlot } = decodeData(
PYTH_INSTRUCTION_LAYOUTS.UpdatePrice,
instruction.data
);
return {
publisherPubkey: instruction.keys[0].pubkey,
pricePubkey: instruction.keys[1].pubkey,
status,
price,
conf,
publishSlot,
};
}
/**
* Decode an "aggregate price" instruction and retrieve the instruction params.
*/
static decodeAggregatePrice(
instruction: TransactionInstruction
): AggregatePriceParams {
decodeData(PYTH_INSTRUCTION_LAYOUTS.AggregatePrice, instruction.data);
return {
fundingPubkey: instruction.keys[0].pubkey,
pricePubkey: instruction.keys[1].pubkey,
};
}
/**
* Decode an "init price" instruction and retrieve the instruction params.
*/
static decodeInitPrice(instruction: TransactionInstruction): InitPriceParams {
const { exponent, priceType } = decodeData(
PYTH_INSTRUCTION_LAYOUTS.InitPrice,
instruction.data
);
return {
fundingPubkey: instruction.keys[0].pubkey,
pricePubkey: instruction.keys[1].pubkey,
exponent,
priceType,
};
}
/**
* Decode an "set min publishers" instruction and retrieve the instruction params.
*/
static decodeSetMinPublishers(
instruction: TransactionInstruction
): SetMinPublishersParams {
const { minPublishers } = decodeData(
PYTH_INSTRUCTION_LAYOUTS.SetMinPublishers,
instruction.data
);
return {
fundingPubkey: instruction.keys[0].pubkey,
pricePubkey: instruction.keys[1].pubkey,
minPublishers,
};
}
}

View File

@ -0,0 +1,13 @@
import { TransactionInstruction } from "@solana/web3.js";
export const PROGRAM_IDS: string[] = [
"gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s", // devnet
"8tfDNiaEyrV6Q1U4DEXrEigs9DoDtkugzFbybENEbCDz", // testnet
"FsJ3A3u2vn5cTVofAjvy6y5kwABJAqYWpe4975bi2epH", // mainnet
];
export function isPythInstruction(
instruction: TransactionInstruction
): boolean {
return PROGRAM_IDS.includes(instruction.programId.toBase58());
}

View File

@ -41,6 +41,8 @@ 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";
import { isPythInstruction } from "components/instruction/pyth/types";
import { PythDetailsCard } from "components/instruction/pyth/PythDetailsCard";
export type InstructionDetailsProps = {
tx: ParsedTransaction;
@ -222,6 +224,8 @@ function renderInstructionCard({
return <TokenLendingDetailsCard key={key} {...props} />;
} else if (isWormholeInstruction(transactionIx)) {
return <WormholeDetailsCard key={key} {...props} />;
} else if (isPythInstruction(transactionIx)) {
return <PythDetailsCard key={key} {...props} />;
} else {
return <UnknownDetailsCard key={key} {...props} />;
}