From 6178e914776a6d0c7f9e56e4faef2ceeb0be9c76 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Fri, 7 Oct 2022 19:08:59 -0300 Subject: [PATCH 01/28] updating polkadot api --- package.json | 14 +- pnpm-lock.yaml | 851 +++++++++--------- .../subscriptions.service.spec.ts | 11 +- src/subscriptions/subscriptions.service.ts | 4 +- 4 files changed, 453 insertions(+), 427 deletions(-) diff --git a/package.json b/package.json index ad8cedd..d7a9ca9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ink-substrate-explorer-api", - "version": "1.0.0", + "version": "1.0.1", "description": "Ink Explorer is an application that provides Ink contracts related information on Substrate based blockchains.", "author": "Blockcoders ", "license": "MIT", @@ -93,12 +93,12 @@ "@nestjs/mapped-types": "1.1.0", "@nestjs/platform-fastify": "8.4.7", "@nestjs/typeorm": "9.0.0", - "@polkadot/api": "^8.14.1", - "@polkadot/api-augment": "^8.14.1", - "@polkadot/api-contract": "^8.14.1", - "@polkadot/types": "^8.14.1", - "@polkadot/types-codec": "^8.14.1", - "@polkadot/types-create": "^8.14.1", + "@polkadot/api": "^9.4.3", + "@polkadot/api-augment": "^9.4.3", + "@polkadot/api-contract": "^9.4.3", + "@polkadot/types": "^9.4.3", + "@polkadot/types-codec": "^9.4.3", + "@polkadot/types-create": "^9.4.3", "@polkadot/util": "10.1.2", "@substrate/txwrapper": "^7.0.1", "@substrate/txwrapper-core": "^3.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e48f59..0d5b8e1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,12 +15,12 @@ specifiers: '@nestjs/schematics': ^8.0.11 '@nestjs/testing': ^8.4.7 '@nestjs/typeorm': 9.0.0 - '@polkadot/api': ^8.14.1 - '@polkadot/api-augment': ^8.14.1 - '@polkadot/api-contract': ^8.14.1 - '@polkadot/types': ^8.14.1 - '@polkadot/types-codec': ^8.14.1 - '@polkadot/types-create': ^8.14.1 + '@polkadot/api': ^9.4.3 + '@polkadot/api-augment': ^9.4.3 + '@polkadot/api-contract': ^9.4.3 + '@polkadot/types': ^9.4.3 + '@polkadot/types-codec': ^9.4.3 + '@polkadot/types-create': ^9.4.3 '@polkadot/util': 10.1.2 '@substrate/txwrapper': ^7.0.1 '@substrate/txwrapper-core': ^3.1.7 @@ -78,12 +78,12 @@ dependencies: '@nestjs/mapped-types': 1.1.0_7zw7e46jhcfuw5vwuwho2brjki '@nestjs/platform-fastify': 8.4.7_7tsmhnugyerf5okgqzer2mfqme '@nestjs/typeorm': 9.0.0_zhrs42futwpjx7z3p6twpp4g7i - '@polkadot/api': 8.14.1 - '@polkadot/api-augment': 8.14.1 - '@polkadot/api-contract': 8.14.1 - '@polkadot/types': 8.14.1 - '@polkadot/types-codec': 8.14.1 - '@polkadot/types-create': 8.14.1 + '@polkadot/api': 9.4.3 + '@polkadot/api-augment': 9.4.3 + '@polkadot/api-contract': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 '@polkadot/util': 10.1.2 '@substrate/txwrapper': 7.0.1 '@substrate/txwrapper-core': 3.1.7 @@ -654,6 +654,13 @@ packages: regenerator-runtime: 0.13.9 dev: false + /@babel/runtime/7.19.0: + resolution: {integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.9 + dev: false + /@babel/template/7.18.10: resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} engines: {node: '>=6.9.0'} @@ -1521,6 +1528,10 @@ packages: resolution: {integrity: sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==} dev: false + /@noble/hashes/1.1.3: + resolution: {integrity: sha512-CE0FCR57H2acVI5UOzIGSSIYxZ6v/HOhDR0Ro9VLyhnzLwx0o8W1mmgaqlEUx4049qJDlIBRztv5k+MM8vbO3A==} + dev: false + /@noble/secp256k1/1.5.5: resolution: {integrity: sha512-sZ1W6gQzYnu45wPrWx8D3kwI2/U29VYTx9OjbDAd7jwRItJ0cSTMPRL/C8AWZFn9kWFLQGqEXVEE86w4Z8LpIQ==} dev: false @@ -1533,6 +1544,10 @@ packages: resolution: {integrity: sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==} dev: false + /@noble/secp256k1/1.7.0: + resolution: {integrity: sha512-kbacwGSsH/CTout0ZnZWxnW1B+jH/7r/WAAKLBtrRJ/+CUH7lgmQzl3GTrQua3SGKWNSDsS6lmjnDpIJ5Dxyaw==} + dev: false + /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1592,7 +1607,7 @@ packages: resolution: {integrity: sha512-7csQLS6zuYuGq7W1EkTBz1ZmxyRvx/Qpz7E7zPSwxmY8Whb7Yn2effU9XF0eCcRpyfSW8LodF8wMmLxGYs1OaQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-base': 7.15.1 '@polkadot/rpc-augment': 7.15.1 '@polkadot/types': 7.15.1 @@ -1608,28 +1623,28 @@ packages: resolution: {integrity: sha512-65GMlgVnZd08Ifh8uAj+p/+MlXxvsAfBcCHjQhOmbCE0dki+rzTPUR31LsWyDKtuw+nUBj0iZN4PelO+wU4r0g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-base': 8.14.1 '@polkadot/rpc-augment': 8.14.1 '@polkadot/types': 8.14.1 '@polkadot/types-augment': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - supports-color dev: false - /@polkadot/api-augment/9.3.3: - resolution: {integrity: sha512-usO5G2lDjzmwrPCgpe9IS5J2gddrDfeuWECc9/ruw35/ag4x8uZkiViC9762pF9fu9ZzNfSrk2QRnVGRcbG1ZQ==} + /@polkadot/api-augment/9.4.3: + resolution: {integrity: sha512-w1iAdfpHprQiPkk9s98vRFqf9AJ70GoheGAEqO6p7JKYoutPlA8Pg8NiacwiCWW464zdbRn/T2/fWGtn8Iv27A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api-base': 9.3.3 - '@polkadot/rpc-augment': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-augment': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/api-base': 9.4.3 + '@polkadot/rpc-augment': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-augment': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - bufferutil - supports-color @@ -1640,11 +1655,11 @@ packages: resolution: {integrity: sha512-UlhLdljJPDwGpm5FxOjvJNFTxXMRFaMuVNx6EklbuetbBEJ/Amihhtj0EJRodxQwtZ4ZtPKYKt+g+Dn7OJJh4g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 7.15.1 '@polkadot/types': 7.15.1 '@polkadot/util': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -1654,51 +1669,53 @@ packages: resolution: {integrity: sha512-EXFhNXIfpirf18IsqcG2pGQW1/Xn+bfjqVYQMMJ4ZONtYH4baZZlXk7SoXCCHonN2x1ixs4DOcRx5oVxjabdIQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 8.14.1 '@polkadot/types': 8.14.1 - '@polkadot/util': 10.1.6 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - supports-color dev: false - /@polkadot/api-base/9.3.3: - resolution: {integrity: sha512-MFjcdwNyqKxoWkqSJRkMtaQogFxsCW6HBVowT0lUrQ2WzTLBWQqi7DcC/0RsRQXXN/SsUwczi3g9b12wqLZLhg==} + /@polkadot/api-base/9.4.3: + resolution: {integrity: sha512-gYzf7LIcKo/rEGlXgoMOS619srcTmyD7wwZ9b0xh/Xg0vHPyUi8OVs3i4SRQrXS8KSVuZzBCrqALPytXmV0xdg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/util': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate dev: false - /@polkadot/api-contract/8.14.1: - resolution: {integrity: sha512-ZIdlSoN5WktQD/Q97cg7MuRcQsFe+4RZDXLew2uUg2R1IyEon+TzEGPXUPVAEQuhlOyRxT6f4/UEM/yTdoGPSQ==} + /@polkadot/api-contract/9.4.3: + resolution: {integrity: sha512-PnBZyUgaLf7DGHkfrRrYISGRXLpZXykJj3L6KKcMrZL7MgiPvyhYzNVXCTmhGOjPQxhaYUDk8VPWmArLf8qT2Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api': 8.14.1 - '@polkadot/types': 8.14.1 - '@polkadot/types-codec': 8.14.1 - '@polkadot/types-create': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/api': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: + - bufferutil - supports-color + - utf-8-validate dev: false /@polkadot/api-derive/4.17.1: resolution: {integrity: sha512-mgq57F1yAiZjuiA0vrR2zWidyyd+mGe7Kbs4SxVeDWLsNbLc9+eASIfX7Hch2SDHIn3CQpv6DQqJH00uDfw9Lw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api': 4.17.1 '@polkadot/rpc-core': 4.17.1 '@polkadot/types': 4.17.1 @@ -1714,7 +1731,7 @@ packages: resolution: {integrity: sha512-CsOQppksQBaa34L1fWRzmfQQpoEBwfH0yTTQxgj3h7rFYGVPxEKGeFjo1+IgI2vXXvOO73Z8E4H/MnbxvKrs1Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api': 7.15.1 '@polkadot/api-augment': 7.15.1 '@polkadot/api-base': 7.15.1 @@ -1723,7 +1740,7 @@ packages: '@polkadot/types-codec': 7.15.1 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -1733,34 +1750,34 @@ packages: resolution: {integrity: sha512-eWG1MrQhHMUjt9gDHN9/9/ZMATu1MolqcalPFhNoGtdON3+I0J3ntjQ4y5X7+p2OGwQplpYRKqbK4k7tKzu8tA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api': 8.14.1 '@polkadot/api-augment': 8.14.1 '@polkadot/api-base': 8.14.1 '@polkadot/rpc-core': 8.14.1 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - supports-color dev: false - /@polkadot/api-derive/9.3.3: - resolution: {integrity: sha512-UiIEKJ0YttgrAqikK/sH0CxedZMijoM33Fuyr4mNWe7srb5MewoABdnwzUMmRVDLjrKA18gtOfSNhqEDliRYGw==} + /@polkadot/api-derive/9.4.3: + resolution: {integrity: sha512-6lKjJs93ucSF/mmljG32TcWq4gg35MimbuXxDYwNYXwuGm6ocN0auWp6Opg+DGLuwapfHhkOyZxSBVWi37gjEQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api': 9.3.3 - '@polkadot/api-augment': 9.3.3 - '@polkadot/api-base': 9.3.3 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/api': 9.4.3 + '@polkadot/api-augment': 9.4.3 + '@polkadot/api-base': 9.4.3 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color @@ -1771,7 +1788,7 @@ packages: resolution: {integrity: sha512-uuNIKWC+PjM+1AARRu4NLWOEudZE6DW8UOlaubx3uGhPywqPIP+HGWP2I6PqRGYKARBWxxOvca1Q7WoKzpYC8w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-derive': 4.17.1 '@polkadot/keyring': 6.11.1 '@polkadot/metadata': 4.17.1 @@ -1792,7 +1809,7 @@ packages: resolution: {integrity: sha512-z0z6+k8+R9ixRMWzfsYrNDnqSV5zHKmyhTCL0I7+1I081V18MJTCFUKubrh0t1gD0/FCt3U9Ibvr4IbtukYLrQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-augment': 7.15.1 '@polkadot/api-base': 7.15.1 '@polkadot/api-derive': 7.15.1 @@ -1808,7 +1825,7 @@ packages: '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 eventemitter3: 4.0.7 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -1818,7 +1835,7 @@ packages: resolution: {integrity: sha512-jg26eIKFYqVfDBTAopHL3aDaNw9j6TdUkXuvYJOnynpecU4xwbTVKcOtSOjJ2eRX4MgMQ4zlyMHJx3iKw0uUTA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-augment': 8.14.1 '@polkadot/api-base': 8.14.1 '@polkadot/api-derive': 8.14.1 @@ -1831,7 +1848,7 @@ packages: '@polkadot/types-codec': 8.14.1 '@polkadot/types-create': 8.14.1 '@polkadot/types-known': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 '@polkadot/util-crypto': 10.1.2 eventemitter3: 4.0.7 rxjs: 7.5.6 @@ -1839,27 +1856,27 @@ packages: - supports-color dev: false - /@polkadot/api/9.3.3: - resolution: {integrity: sha512-esOfwnKS/6JRL0C8TDqYn4GC9GkWp8vTdKIWLuncW2jEtiJLYccb5IVngfOQImVrqAQoV1hJdLnj9X6k+tGqQQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api-augment': 9.3.3 - '@polkadot/api-base': 9.3.3 - '@polkadot/api-derive': 9.3.3 - '@polkadot/keyring': 10.1.7 - '@polkadot/rpc-augment': 9.3.3 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/rpc-provider': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-augment': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/types-create': 9.3.3 - '@polkadot/types-known': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 + /@polkadot/api/9.4.3: + resolution: {integrity: sha512-vbeWW2tyntAmWllUqnOwlaprFT+5o8a0uP0Qkz5QfLslUFZtxhHhLWtQWVtJnoqC5FN10ZybDkUGFlsxNsvwgg==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/api-augment': 9.4.3 + '@polkadot/api-base': 9.4.3 + '@polkadot/api-derive': 9.4.3 + '@polkadot/keyring': 10.1.10 + '@polkadot/rpc-augment': 9.4.3 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/rpc-provider': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-augment': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/types-known': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 eventemitter3: 4.0.7 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color @@ -1913,29 +1930,29 @@ packages: - utf-8-validate dev: false - /@polkadot/keyring/10.1.2: - resolution: {integrity: sha512-b6hP3JFGYjsNNT3NO7I8fWRPqovgL4IvjvLttkfzpM6eM1zRRupqQ+Q50Jdl/3YUcr26PcxQcdRqJku4WyDABg==} + /@polkadot/keyring/10.1.10: + resolution: {integrity: sha512-crKYBbwmPcFoTP6mby2+o1QWsjAyi5QlKzU8tXuXOApP6SBuqmDujIuLOKNG2vZoftNdVldsVL0WmKVYtBeuQg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 - '@polkadot/util-crypto': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 dev: false - /@polkadot/keyring/10.1.7: - resolution: {integrity: sha512-lArwaAS3hDs+HHupDIC4r2mFaAfmNQV2YzwL2wM5zhOqB2RugN03BFrgwNll0y9/Bg8rYDqM3Y5BvVMzgMZ6XA==} + /@polkadot/keyring/10.1.2: + resolution: {integrity: sha512-b6hP3JFGYjsNNT3NO7I8fWRPqovgL4IvjvLttkfzpM6eM1zRRupqQ+Q50Jdl/3YUcr26PcxQcdRqJku4WyDABg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 + '@polkadot/util-crypto': 10.1.2 dev: false /@polkadot/keyring/6.11.1: resolution: {integrity: sha512-rW8INl7pO6Dmaffd6Df1yAYCRWa2RmWQ0LGfJeA/M6seVIkI6J3opZqAd4q2Op+h9a7z4TESQGk8yggOEL+Csg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 '@polkadot/util-crypto': 6.11.1 dev: false @@ -1944,7 +1961,7 @@ packages: resolution: {integrity: sha512-6UGoIxhiTyISkYEZhUbCPpgVxaneIfb/DBVlHtbvaABc8Mqh1KuqcTIq19Mh9wXlBuijl25rw4lUASrE/9sBqg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 '@polkadot/util-crypto': 7.9.2 dev: false @@ -1953,7 +1970,7 @@ packages: resolution: {integrity: sha512-t6ZgQVC+nQT7XwbWtEhkDpiAzxKVJw8Xd/gWdww6xIrawHu7jo3SGB4QNdPgkf8TvDHYAAJiupzVQYAlOIq3GA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 dev: false @@ -1962,7 +1979,7 @@ packages: resolution: {integrity: sha512-219isiCWVfbu5JxZnOPj+cV4T+S0XHS4+Jal3t3xz9y4nbgr+25Pa4KInEsJPx0u8EZAxMeiUCX3vd5U7oe72g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 4.17.1 '@polkadot/types-known': 4.17.1 '@polkadot/util': 6.11.1 @@ -1978,43 +1995,43 @@ packages: '@substrate/ss58-registry': 1.25.0 dev: false - /@polkadot/networks/10.1.2: - resolution: {integrity: sha512-67ZPqdhLYDGNX1jMEa3+hujh9j30Dr9AdqgdjE8Z3GdWoEVRp9Zda3DXMnDIQlRBQ32pRZty7dFhIq61Bv/whQ==} + /@polkadot/networks/10.1.10: + resolution: {integrity: sha512-Db78t2XnFIZbdSdu1aFuj3/1cNwcSzG/+wNrpCQ9dPhnGPy5S1GVbmU8pyxTftPKdTFc+8RdBr+5bc0d5ijGiA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 - '@substrate/ss58-registry': 1.25.0 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@substrate/ss58-registry': 1.31.0 dev: false - /@polkadot/networks/10.1.7: - resolution: {integrity: sha512-ol864SZ/GwAF72GQOPRy+Y9r6NtgJJjMBlDLESvV5VK64eEB0MRSSyiOdd7y/4SumR9crrrNimx3ynACFgxZ8A==} + /@polkadot/networks/10.1.2: + resolution: {integrity: sha512-67ZPqdhLYDGNX1jMEa3+hujh9j30Dr9AdqgdjE8Z3GdWoEVRp9Zda3DXMnDIQlRBQ32pRZty7dFhIq61Bv/whQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@substrate/ss58-registry': 1.28.0 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 + '@substrate/ss58-registry': 1.25.0 dev: false /@polkadot/networks/6.11.1: resolution: {integrity: sha512-0C6Ha2kvr42se3Gevx6UhHzv3KnPHML0N73Amjwvdr4y0HLZ1Nfw+vcm5yqpz5gpiehqz97XqFrsPRauYdcksQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/networks/7.9.2: resolution: {integrity: sha512-4obI1RdW5/7TFwbwKA9oqw8aggVZ65JAUvIFMd2YmMC2T4+NiZLnok0WhRkhZkUnqjLIHXYNwq7Ho1i39dte0g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/networks/8.7.1: resolution: {integrity: sha512-8xAmhDW0ry5EKcEjp6VTuwoTm0DdDo/zHsmx88P6sVL87gupuFsL+B6TrsYLl8GcaqxujwrOlKB+CKTUg7qFKg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 '@substrate/ss58-registry': 1.25.0 dev: false @@ -2023,7 +2040,7 @@ packages: resolution: {integrity: sha512-oMAdF8Y9CLBI0EUZBcycHcvbQQdbkJHevPJ/lwnZXJTaueXuav/Xm2yiFj5J3V8meIjLocURlMawgsAVItXOBQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@substrate/ss58-registry': 1.25.0 dev: false @@ -2032,7 +2049,7 @@ packages: resolution: {integrity: sha512-sK0+mphN7nGz/eNPsshVi0qd0+N0Pqxuebwc1YkUGP0f9EkDxzSGp6UjGcSwWVaAtk9WZZ1MpK1Jwb/2GrKV7Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 7.15.1 '@polkadot/types': 7.15.1 '@polkadot/types-codec': 7.15.1 @@ -2046,24 +2063,24 @@ packages: resolution: {integrity: sha512-0dIsNVIMeCp0kV7+Obz0Odt6K32Ka2ygwhiV5jhhJthy8GJBPo94mKDed5gzln3Dgl2LEdJJt1h/pgCx4a2i4A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 8.14.1 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - supports-color dev: false - /@polkadot/rpc-augment/9.3.3: - resolution: {integrity: sha512-xU+Fc1gm3C0CvFl2+38LN5qAdyw4ECSj2qxTymro6jqnHxpiyCvRtMg5Grl3MzREVFwhthg80W19jT1hjdPhyg==} + /@polkadot/rpc-augment/9.4.3: + resolution: {integrity: sha512-j4oFAPfP+AyQVb1rl8Jbj5k0UqfZyHUy0+CLHtu/Q0S9Wk0R1SDPACpI+93H0DjwYAFfsxbRMhloAH1IJWD5uA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - bufferutil - supports-color @@ -2074,7 +2091,7 @@ packages: resolution: {integrity: sha512-1gqYaYuSSQsRmt3ol55jmjBP/euKyAh4PwSj94I2wu0fngK/FZwVZNDJZn/Ib68X/s38TBIgqJ6+YdUdr3z1xw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/metadata': 4.17.1 '@polkadot/rpc-provider': 4.17.1 '@polkadot/types': 4.17.1 @@ -2089,12 +2106,12 @@ packages: resolution: {integrity: sha512-4Sb0e0PWmarCOizzxQAE1NQSr5z0n+hdkrq3+aPohGu9Rh4PodG+OWeIBy7Ov/3GgdhNQyBLG+RiVtliXecM3g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-augment': 7.15.1 '@polkadot/rpc-provider': 7.15.1 '@polkadot/types': 7.15.1 '@polkadot/util': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -2104,26 +2121,26 @@ packages: resolution: {integrity: sha512-deQ8Ob59ao/1fZQdaVtFjYR/HCBdxSYvQGt7/alBu1Uig9Sahx9oKcMkU5rWY36XqGZYos4zLay98W2hDlf+6Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-augment': 8.14.1 '@polkadot/rpc-provider': 8.14.1 '@polkadot/types': 8.14.1 - '@polkadot/util': 10.1.6 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - supports-color dev: false - /@polkadot/rpc-core/9.3.3: - resolution: {integrity: sha512-KMT98HeYt6IpFvTRKWhFkHxQvGhuVIT0gyOjvT+hmuDQqt3k3bcgoQSR7218uD51NNYhnZJpjAKl3LTJz2Fdgg==} + /@polkadot/rpc-core/9.4.3: + resolution: {integrity: sha512-xTU33bNnqdLaaCFdGnoxY03rmmgUKH/2JoEa+fBRvt9RPc7KuanWSKSeHieekZXSgCXBJ3zbfStyo43klg74OQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/rpc-augment': 9.3.3 - '@polkadot/rpc-provider': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/util': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/rpc-augment': 9.4.3 + '@polkadot/rpc-provider': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color @@ -2134,7 +2151,7 @@ packages: resolution: {integrity: sha512-vlU1H5mnfP0Ej8PbjcxwF9ZlT7LtcpekOKI4iYfMnfdelSUKUVyaD5PC8yRGIg9fxkorA6OM5AZs116jAl3TLA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 4.17.1 '@polkadot/util': 6.11.1 '@polkadot/util-crypto': 6.11.1 @@ -2151,7 +2168,7 @@ packages: resolution: {integrity: sha512-n0RWfSaD/r90JXeJkKry1aGZwJeBUUiMpXUQ9Uvp6DYBbYEDs0fKtWLpdT3PdFrMbe5y3kwQmNLxwe6iF4+mzg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 8.7.1 '@polkadot/types': 7.15.1 '@polkadot/types-support': 7.15.1 @@ -2173,12 +2190,12 @@ packages: resolution: {integrity: sha512-pAUSHZiSWLhBSYf4LmLc8iCaeqTu7Ajn8AzyqxvZDHGnIrzV5M7eTjpNDP84qno6jWRHKQ/IILr62hausEmS5w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 10.1.2 '@polkadot/types': 8.14.1 '@polkadot/types-support': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 '@polkadot/x-fetch': 10.1.2 '@polkadot/x-global': 10.1.6 '@polkadot/x-ws': 10.1.2 @@ -2190,20 +2207,20 @@ packages: - supports-color dev: false - /@polkadot/rpc-provider/9.3.3: - resolution: {integrity: sha512-A5eX5WfG5JeYXUNRBOEGtSqvmQN6jqbrAmXkufSWYvGb/1Ip2l/9oHuUjswGLdpaWfOkpVkClyCXIFtWx06XNw==} + /@polkadot/rpc-provider/9.4.3: + resolution: {integrity: sha512-8HCkwlDnH6Y6WNT0Yg8e6YM5Wk+GacnO906nhtHByR2MRL8ugvLRb0x97PSPrR+NYs+ecYUURFkRy0fujuFcHQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/keyring': 10.1.7 - '@polkadot/types': 9.3.3 - '@polkadot/types-support': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 - '@polkadot/x-fetch': 10.1.7 - '@polkadot/x-global': 10.1.7 - '@polkadot/x-ws': 10.1.7 - '@substrate/connect': 0.7.11 + '@babel/runtime': 7.19.0 + '@polkadot/keyring': 10.1.10 + '@polkadot/types': 9.4.3 + '@polkadot/types-support': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + '@polkadot/x-fetch': 10.1.10 + '@polkadot/x-global': 10.1.10 + '@polkadot/x-ws': 10.1.10 + '@substrate/connect': 0.7.14 eventemitter3: 4.0.7 mock-socket: 9.1.5 nock: 13.2.9 @@ -2217,7 +2234,7 @@ packages: resolution: {integrity: sha512-aqm7xT/66TCna0I2utpIekoquKo0K5pnkA/7WDzZ6gyD8he2h0IXfe8xWjVmuyhjxrT/C/7X1aUF2Z0xlOCwzQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 7.15.1 '@polkadot/types-codec': 7.15.1 '@polkadot/util': 8.7.1 @@ -2227,27 +2244,27 @@ packages: resolution: {integrity: sha512-Xa4TUFqyZT+IJ6pBSwDjWcF42u/E34OyC+gbs5Z2vWQ4EzSDkq4xNoUKjJlEEgTemsD9lhPOIc4jvqTCefwxEw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-augment/9.3.3: - resolution: {integrity: sha512-XAhyX5DEYnsMunpoU1podjm5ODosTmMwwpNcUK95ALcyzkpstyWIjUW3JhaEOzIshsYmJUNxM7/cSI4jv/VLAg==} + /@polkadot/types-augment/9.4.3: + resolution: {integrity: sha512-TvN3vhUVylFyWGHHXOO4/iHIFW6EXHLBlIBC7YhUQc0dZOD+mKjnNblEtDY/GazlwBQjq9bhXcoH0S6KIpiSIg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types-codec/7.15.1: resolution: {integrity: sha512-nI11dT7FGaeDd/fKPD8iJRFGhosOJoyjhZ0gLFFDlKCaD3AcGBRTTY8HFJpP/5QXXhZzfZsD93fVKrosnegU0Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false @@ -2255,25 +2272,25 @@ packages: resolution: {integrity: sha512-y6YDN4HwvEgSWlgrEV04QBBxDxES1cTuUQFzZJzOTuZCWpA371Mdj3M9wYxGXMnj0wa+rCQGECHPZZaNxBMiKg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.6 - '@polkadot/x-bigint': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/x-bigint': 10.1.10 dev: false - /@polkadot/types-codec/9.3.3: - resolution: {integrity: sha512-DiSGZ/pwZO0huS4CnyI0Z4nsvKSFUAjjcVQ7lt1BqCRcUFoIZtYQgzXftia1kSXnJs4J13PMcFTfQZeTDnp4Sg==} + /@polkadot/types-codec/9.4.3: + resolution: {integrity: sha512-x0BJZxcPyollDx9urF7rAfDdKHZXe150p9op2if8fw02LNTDGGsrWLw7DD8ISNwXbtL8L+N1ipc0mVqfsHg+Aw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/x-bigint': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/x-bigint': 10.1.10 dev: false /@polkadot/types-create/7.15.1: resolution: {integrity: sha512-+HiaHn7XOwP0kv/rVdORlVkNuMoxuvt+jd67A/CeEreJiXqRLu+S61Mdk7wi6719PTaOal1hTDFfyGrtUd8FSQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types-codec': 7.15.1 '@polkadot/util': 8.7.1 dev: false @@ -2282,25 +2299,25 @@ packages: resolution: {integrity: sha512-fb9yyblj5AYAPzeCIq0kYSfzDxRDi/0ud9gN2UzB3H7M/O4n2mPC1vD4UOLF+B7l9QzCrt4e+k+/riGp7GfvyA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-create/9.3.3: - resolution: {integrity: sha512-LRS5sWYtPyXZ8AC7j9foFQQzYhay2q4YnXD9Hfz2ULrjtpjdUgR0hP3GpBKfxDnlWESpzGjegSAIDs+z/sKnfA==} + /@polkadot/types-create/9.4.3: + resolution: {integrity: sha512-kx5Yccp/I4RrtbOo3+iFJSVDwbl0Y9Xm0B4p7khYkKUHAbNuuFZMMnnMru2hOTWDgpQPN6Fbixt9pdy4TD6Xnw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types-known/4.17.1: resolution: {integrity: sha512-YkOwGrO+k9aVrBR8FgYHnfJKhOfpdgC5ZRYNL/xJ9oa7lBYqPts9ENAxeBmJS/5IGeDF9f32MNyrCP2umeCXWg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 6.11.1 '@polkadot/types': 4.17.1 '@polkadot/util': 6.11.1 @@ -2310,7 +2327,7 @@ packages: resolution: {integrity: sha512-Z8bHpPQy+mqUm0uR1tai6ra0bQIoPmgRcGFYUM+rJtW1kx/6kZLh10HAICjLpPeA1cwLRzaxHRDqH5MCU6OgXw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 8.7.1 '@polkadot/types': 6.12.1 '@polkadot/util': 8.7.1 @@ -2320,7 +2337,7 @@ packages: resolution: {integrity: sha512-LMcNP0CxT84DqAKV62/qDeeIVIJCR5yzE9b+9AsYhyfhE4apwxjrThqZA7K0CF56bOdQJSexAerYB/jwk2IijA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 8.7.1 '@polkadot/types': 7.15.1 '@polkadot/types-codec': 7.15.1 @@ -2332,31 +2349,31 @@ packages: resolution: {integrity: sha512-GP7gRo9nmitykkrRnoLF61Qm19UFdTwMsOnJkdm7AOeWDmZGxutacgO6k1tBsHr38hsiCCGsB/JiseUgywvGIw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 10.1.2 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 '@polkadot/types-create': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-known/9.3.3: - resolution: {integrity: sha512-TcDGzHpPZdMxrywLHTbjaHaFRdJdFaL5QGpvcSeDwAGHz7zU6Aq29AT9HwJ8GrBNihLALUj79S1/D2WfmJuXFA==} + /@polkadot/types-known/9.4.3: + resolution: {integrity: sha512-JoIC31If1tLhz4ykNCcJCJGEuufJo7c880vCDLzdYn/OCxxHvdrUeNAFZu0ua/QNHNpT7Pl24NGUrE2QfmZbRg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/networks': 10.1.7 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/types-create': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/networks': 10.1.10 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types-support/7.15.1: resolution: {integrity: sha512-FIK251ffVo+NaUXLlaJeB5OvT7idDd3uxaoBM6IwsS87rzt2CcWMyCbu0uX89AHZUhSviVx7xaBxfkGEqMePWA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false @@ -2364,23 +2381,23 @@ packages: resolution: {integrity: sha512-XqR4qq6pCZyNBuFVod8nFSNUmLssrjoU9bOIn4Ua2cqNlI9xsuKaI1X5ySEn/oWOtKQ2L5hbCm9vkXrEtXBl1w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.6 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-support/9.3.3: - resolution: {integrity: sha512-KJeL3bBc8XEIDuUFjYLBunAvMkVi8LXdln4V1FPHEt6OgXkbqJlc9KAwgrPUaV1+Ki0LIBDDYKtUiMG3c9Ip+g==} + /@polkadot/types-support/9.4.3: + resolution: {integrity: sha512-PCIHVj40A5qgUQJHOM4BpeVwXPVNo0PNeVVWMPPLdnUMr3hX8dqCjZnWAUizgTICJ5EutCLL5wKP6/JBZmmWsA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types/4.17.1: resolution: {integrity: sha512-rjW4OFdwvFekzN3ATLibC2JPSd8AWt5YepJhmuCPdwH26r3zB8bEC6dM7YQExLVUmygVPvgXk5ffHI6RAdXBMg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/metadata': 4.17.1 '@polkadot/util': 6.11.1 '@polkadot/util-crypto': 6.11.1 @@ -2391,84 +2408,84 @@ packages: resolution: {integrity: sha512-O37cAGUL0xiXTuO3ySweVh0OuFUD6asrd0TfuzGsEp3jAISWdElEHV5QDiftWq8J9Vf8BMgTcP2QLFbmSusxqA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types-known': 6.12.1 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 dev: false /@polkadot/types/7.15.1: resolution: {integrity: sha512-KawZVS+eLR1D6O7c/P5cSUwr6biM9Qd2KwKtJIO8l1Mrxp7r+y2tQnXSSXVAd6XPdb3wVMhnIID+NW3W99TAnQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 8.7.1 '@polkadot/types-augment': 7.15.1 '@polkadot/types-codec': 7.15.1 '@polkadot/types-create': 7.15.1 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 dev: false /@polkadot/types/8.14.1: resolution: {integrity: sha512-Xza16ejKrSd4XhTOlbfISyxZ2sRmbMAZk5pX7VEMHVZHqV98o+bJ2f9Kk7F8YJijkHHGosCLDestP9R5nLoOoA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 10.1.2 '@polkadot/types-augment': 8.14.1 '@polkadot/types-codec': 8.14.1 '@polkadot/types-create': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 dev: false - /@polkadot/types/9.3.3: - resolution: {integrity: sha512-By7VC9erdsJCDR9DNtgSuWSrKeLpJ7tnStS8Ii31LW1ueYDWCx1CO28fogq4UYf53pMbhNCWDGPFk1ZZn8ZchA==} + /@polkadot/types/9.4.3: + resolution: {integrity: sha512-SXHih0+TajRAZAl+uuFPpy/TxySX8oYvYg67FwRclqNsHc1Qwj5JFs0HJtuf60UkvPGqbQpNek5ND6O1VBHHQA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/keyring': 10.1.7 - '@polkadot/types-augment': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/types-create': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/keyring': 10.1.10 + '@polkadot/types-augment': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 dev: false - /@polkadot/util-crypto/10.1.2: - resolution: {integrity: sha512-lSgxSLF/XkksL8St3kyw8SCLic0JvyIf8uOezQZYyjSJKT3Gl8gGu9wCAKNAmboU0FgO8cnLO9AcAEkhCHvnyw==} + /@polkadot/util-crypto/10.1.10: + resolution: {integrity: sha512-w9h/wf4wZXeUkRnihhnfqlaKuoQtrjkjK3C5liCQkr9vx5zOsmg/nMSDP8UUFJX0msPPYpFeNvzn7oDIs6qSZA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@noble/hashes': 1.1.2 - '@noble/secp256k1': 1.6.3 - '@polkadot/networks': 10.1.2 - '@polkadot/util': 10.1.2 - '@polkadot/wasm-crypto': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm - '@polkadot/x-bigint': 10.1.2 - '@polkadot/x-randomvalues': 10.1.2 + '@babel/runtime': 7.19.0 + '@noble/hashes': 1.1.3 + '@noble/secp256k1': 1.7.0 + '@polkadot/networks': 10.1.10 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-crypto': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/x-bigint': 10.1.10 + '@polkadot/x-randomvalues': 10.1.10 '@scure/base': 1.1.1 ed2curve: 0.3.0 tweetnacl: 1.0.3 dev: false - /@polkadot/util-crypto/10.1.7: - resolution: {integrity: sha512-zGmSU7a0wdWfpDtfc+Q7fUuW+extu9o1Uh4JpkuwwZ/dxmyW5xlfqVsIScM1pdPyjJsyamX8KwsKiVsW4slasg==} + /@polkadot/util-crypto/10.1.2: + resolution: {integrity: sha512-lSgxSLF/XkksL8St3kyw8SCLic0JvyIf8uOezQZYyjSJKT3Gl8gGu9wCAKNAmboU0FgO8cnLO9AcAEkhCHvnyw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@noble/hashes': 1.1.2 '@noble/secp256k1': 1.6.3 - '@polkadot/networks': 10.1.7 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-crypto': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/x-bigint': 10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@polkadot/networks': 10.1.2 + '@polkadot/util': 10.1.2 + '@polkadot/wasm-crypto': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm + '@polkadot/x-bigint': 10.1.2 + '@polkadot/x-randomvalues': 10.1.2 '@scure/base': 1.1.1 ed2curve: 0.3.0 tweetnacl: 1.0.3 @@ -2478,7 +2495,7 @@ packages: resolution: {integrity: sha512-fWA1Nz17FxWJslweZS4l0Uo30WXb5mYV1KEACVzM+BSZAvG5eoiOAYX6VYZjyw6/7u53XKrWQlD83iPsg3KvZw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 6.11.1 '@polkadot/util': 6.11.1 '@polkadot/wasm-crypto': 4.6.1_7agzzbeuhezrwkh2zmxh2lt2xi @@ -2500,7 +2517,7 @@ packages: resolution: {integrity: sha512-nNwqUwP44eCH9jKKcPie+IHLKkg9LMe6H7hXo91hy3AtoslnNrT51tP3uAm5yllhLvswJfnAgnlHq7ybCgqeFw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 7.9.2 '@polkadot/util': 7.9.2 '@polkadot/wasm-crypto': 4.6.1_dqtjokeiluc5zkdxxwbtwmatza @@ -2522,7 +2539,7 @@ packages: resolution: {integrity: sha512-TaSuJ2aNrB5sYK7YXszkEv24nYJKRFqjF2OrggoMg6uYxUAECvTkldFnhtgeizMweRMxJIBu6bMHlSIutbWgjw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@noble/hashes': 1.0.0 '@noble/secp256k1': 1.5.5 '@polkadot/networks': 8.7.1 @@ -2539,7 +2556,7 @@ packages: resolution: {integrity: sha512-tfz6mJtPwoNteivKCmR+QklC4mr1/hGZRsDJLWKaFhanDinYZ3V2pJM1EbCI6WONLuuzlTxsDXjAffWzzRqlPA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@noble/hashes': 1.1.2 '@noble/secp256k1': 1.6.0 '@polkadot/networks': 9.7.2 @@ -2565,6 +2582,19 @@ packages: bn.js: 5.2.1 dev: false + /@polkadot/util/10.1.10: + resolution: {integrity: sha512-BQoTfSxZ3BWAgWDjgKBVdyw1AJGaoOeAidCA+LZcHV6wlMu5643AZPUnoMrW413MbbpxsIhJXtNttqOwjo8MjA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-bigint': 10.1.10 + '@polkadot/x-global': 10.1.10 + '@polkadot/x-textdecoder': 10.1.10 + '@polkadot/x-textencoder': 10.1.10 + '@types/bn.js': 5.1.1 + bn.js: 5.2.1 + dev: false + /@polkadot/util/10.1.2: resolution: {integrity: sha512-gYSpJyrrw5gZWgTVu6PJ1PBUzi3GqwmaK6XRgi4deHmQRn9TEXTToGtHmleJWnaTCRW8Vvh5B5RNNV2C/+va4w==} engines: {node: '>=14.0.0'} @@ -2582,7 +2612,7 @@ packages: resolution: {integrity: sha512-k+gCKmgwxp0smmLIR7SfiEYEToayWXjrC7pQ0PqAGxpBNOdVMSCzLMnOHf9AI5cjs/lx6ULr1fHn721wLVonkw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-bigint': 10.1.6 '@polkadot/x-global': 10.1.6 '@polkadot/x-textdecoder': 10.1.6 @@ -2591,24 +2621,11 @@ packages: bn.js: 5.2.1 dev: false - /@polkadot/util/10.1.7: - resolution: {integrity: sha512-s7gDLdNb4HUpoe3faXwoO6HwiUp8pi66voYKiUYRh1kEtW1o9vGBgyZPHPGC/FBgILzTJKii/9XxnSex60zBTA==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-bigint': 10.1.7 - '@polkadot/x-global': 10.1.7 - '@polkadot/x-textdecoder': 10.1.7 - '@polkadot/x-textencoder': 10.1.7 - '@types/bn.js': 5.1.1 - bn.js: 5.2.1 - dev: false - /@polkadot/util/6.11.1: resolution: {integrity: sha512-TEdCetr9rsdUfJZqQgX/vxLuV4XU8KMoKBMJdx+JuQ5EWemIdQkEtMBdL8k8udNGbgSNiYFA6rPppATeIxAScg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-textdecoder': 6.11.1 '@polkadot/x-textencoder': 6.11.1 '@types/bn.js': 4.11.6 @@ -2621,7 +2638,7 @@ packages: resolution: {integrity: sha512-6ABY6ErgkCsM4C6+X+AJSY4pBGwbKlHZmUtHftaiTvbaj4XuA4nTo3GU28jw8wY0Jh2cJZJvt6/BJ5GVkm5tBA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-textdecoder': 7.9.2 '@polkadot/x-textencoder': 7.9.2 '@types/bn.js': 4.11.6 @@ -2634,12 +2651,12 @@ packages: resolution: {integrity: sha512-XjY1bTo7V6OvOCe4yn8H2vifeuBciCy0gq0k5P1tlGUQLI/Yt0hvDmxcA0FEPtqg8CL+rYRG7WXGPVNjkrNvyQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-bigint': 8.7.1 '@polkadot/x-global': 8.7.1 '@polkadot/x-textdecoder': 8.7.1 '@polkadot/x-textencoder': 8.7.1 - '@types/bn.js': 5.1.0 + '@types/bn.js': 5.1.1 bn.js: 5.2.1 ip-regex: 4.3.0 dev: false @@ -2648,12 +2665,12 @@ packages: resolution: {integrity: sha512-ivTmA+KkPCq5i3O0Gk+dTds/hwdwlYCh89aKfeaG9ni3XHUbbuBgTqHneo648HqxwAwSAyiDiwE9EdXrzAdO4Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-bigint': 9.7.2 '@polkadot/x-global': 9.7.2 '@polkadot/x-textdecoder': 9.7.2 '@polkadot/x-textencoder': 9.7.2 - '@types/bn.js': 5.1.0 + '@types/bn.js': 5.1.1 bn.js: 5.2.1 ip-regex: 4.3.0 dev: false @@ -2665,7 +2682,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/x-randomvalues': 9.7.2 dev: false @@ -2677,21 +2694,21 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 10.1.2 '@polkadot/x-randomvalues': 10.1.2 dev: false - /@polkadot/wasm-bridge/6.3.1_iavvhndpjoeut6ernjqjjplteq: + /@polkadot/wasm-bridge/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-1TYkHsb9AEFhU9uZj3biEnN2yKQNzdrwSjiTvfCYnt97pnEkKsZI6cku+YPZQv5w/x9CQa5Yua9e2DVVZSivGA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/x-randomvalues': 10.1.10 dev: false /@polkadot/wasm-crypto-asmjs/4.6.1_@polkadot+util@6.11.1: @@ -2700,7 +2717,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 dev: false @@ -2710,7 +2727,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 dev: false @@ -2720,28 +2737,28 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false - /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.2: + /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.10: resolution: {integrity: sha512-zbombRfA5v/mUWQQhgg2YwaxhRmxRIrvskw65x+lruax3b6xPBFDs7yplopiJU3r8h2pTgQvX/DUksvqz2TCRQ==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.7: + /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-zbombRfA5v/mUWQQhgg2YwaxhRmxRIrvskw65x+lruax3b6xPBFDs7yplopiJU3r8h2pTgQvX/DUksvqz2TCRQ==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 dev: false /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@9.7.2: @@ -2750,7 +2767,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 dev: false @@ -2761,7 +2778,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/wasm-bridge': 6.3.1_bqbpofxh4fwo2uvuz4bljqm3ua '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@9.7.2 @@ -2776,7 +2793,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 10.1.2 '@polkadot/wasm-bridge': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.2 @@ -2784,19 +2801,19 @@ packages: '@polkadot/x-randomvalues': 10.1.2 dev: false - /@polkadot/wasm-crypto-init/6.3.1_iavvhndpjoeut6ernjqjjplteq: + /@polkadot/wasm-crypto-init/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-9yaUBcu+snwjJLmPPGl3cyGRQ1afyFGm16qzTM0sgG/ZCfUlK4uk8KWZe+sBUKgoxb2oXY7Y4WklKgQI1YBdfw==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-bridge': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-bridge': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/x-randomvalues': 10.1.10 dev: false /@polkadot/wasm-crypto-wasm/4.6.1_@polkadot+util@6.11.1: @@ -2805,7 +2822,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 dev: false @@ -2815,7 +2832,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 dev: false @@ -2825,30 +2842,30 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false - /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.2: + /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.10: resolution: {integrity: sha512-idSlzKGVzCfeCMRHsacRvqwojSaTadFxL/Dbls4z1thvfa3U9Ku0d2qVtlwg7Hj+tYWDiuP8Kygs+6bQwfs0XA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 - '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.10 dev: false - /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.7: + /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-idSlzKGVzCfeCMRHsacRvqwojSaTadFxL/Dbls4z1thvfa3U9Ku0d2qVtlwg7Hj+tYWDiuP8Kygs+6bQwfs0XA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.2 dev: false /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@9.7.2: @@ -2857,7 +2874,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/wasm-util': 6.3.1_@polkadot+util@9.7.2 dev: false @@ -2869,7 +2886,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 '@polkadot/wasm-crypto-asmjs': 4.6.1_@polkadot+util@6.11.1 '@polkadot/wasm-crypto-wasm': 4.6.1_@polkadot+util@6.11.1 @@ -2883,7 +2900,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 '@polkadot/wasm-crypto-asmjs': 4.6.1_@polkadot+util@7.9.2 '@polkadot/wasm-crypto-wasm': 4.6.1_@polkadot+util@7.9.2 @@ -2897,7 +2914,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 '@polkadot/wasm-crypto-asmjs': 5.1.1_@polkadot+util@8.7.1 '@polkadot/wasm-crypto-wasm': 5.1.1_@polkadot+util@8.7.1 @@ -2911,7 +2928,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/wasm-bridge': 6.3.1_bqbpofxh4fwo2uvuz4bljqm3ua '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@9.7.2 @@ -2928,7 +2945,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 10.1.2 '@polkadot/wasm-bridge': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.2 @@ -2938,41 +2955,41 @@ packages: '@polkadot/x-randomvalues': 10.1.2 dev: false - /@polkadot/wasm-crypto/6.3.1_iavvhndpjoeut6ernjqjjplteq: + /@polkadot/wasm-crypto/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-OO8h0qeVkqp4xYZaRVl4iuWOEtq282pNBHDKb6SOJuI2g59eWGcKh4EQU9Me2VP6qzojIqptrkrVt7KQXC68gA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-bridge': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/wasm-crypto-init': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-bridge': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/wasm-crypto-init': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/x-randomvalues': 10.1.10 dev: false - /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.2: + /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.10: resolution: {integrity: sha512-12oAv5J7Yoc9m6jixrSaQCxpOkWOyzHx3DMC8qmLjRiwdBWxqLmImOVRVnFsbaxqSbhBIHRuJphVxWE+GZETDg==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.7: + /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-12oAv5J7Yoc9m6jixrSaQCxpOkWOyzHx3DMC8qmLjRiwdBWxqLmImOVRVnFsbaxqSbhBIHRuJphVxWE+GZETDg==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 dev: false /@polkadot/wasm-util/6.3.1_@polkadot+util@9.7.2: @@ -2981,7 +2998,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 dev: false @@ -2993,6 +3010,14 @@ packages: '@polkadot/x-global': 10.1.1 dev: false + /@polkadot/x-bigint/10.1.10: + resolution: {integrity: sha512-4Jt0BO0WTby6r9A2DgkDxf/LFaICQHvSl1VSFtBf0Z0GV2n4OxkBX5x/1bdEdGEvYT5rM7RbR3xI7EL+W1ixHA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 + dev: false + /@polkadot/x-bigint/10.1.2: resolution: {integrity: sha512-TCwv3NjQdfLb7CBYR8EA5t0CrMfYx3IF4hKjctuplL+mDNI0VzNn4qVKW62AjouI8kMbn7VyBPfoBeuYX8Ixrw==} engines: {node: '>=14.0.0'} @@ -3005,23 +3030,15 @@ packages: resolution: {integrity: sha512-yeBZQ9+u49KqDBaeSw+ytshqzyaScKrDjAxpWCfOGxJaB+5Nv1W7fqi3OJ4S/HN5DYItr0a6UC14e1hiZUtZCg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 10.1.6 dev: false - /@polkadot/x-bigint/10.1.7: - resolution: {integrity: sha512-uaClHpI6cnDumIfejUKvNTkB43JleEb0V6OIufDKJ/e1aCLE3f/Ws9ggwL8ea05lQP5k5xqOzbPdizi/UvrgKQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 - dev: false - /@polkadot/x-bigint/8.7.1: resolution: {integrity: sha512-ClkhgdB/KqcAKk3zA6Qw8wBL6Wz67pYTPkrAtImpvoPJmR+l4RARauv+MH34JXMUNlNb3aUwqN6lq2Z1zN+mJg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3029,26 +3046,26 @@ packages: resolution: {integrity: sha512-qi8/DTGypFSt5vvNOsYcEaqH72lymfyidGlsHlZ6e7nNASnEhk/NaOcINiTr1ds+fpu4dtKXWAIPZufujf2JeQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false - /@polkadot/x-fetch/10.1.2: - resolution: {integrity: sha512-Zd7npq9H/kDaehiM2iyPX1+cSfuhCvqDxuS8GLTjARIVGGURBfA+NjRM6o6jsXa3HCtv+lB67Qdw1m/PSxfIpQ==} + /@polkadot/x-fetch/10.1.10: + resolution: {integrity: sha512-LvTxAN6GaJzfgZ74WFYPZrIkMEThpX5u7O4ILiExcJt87E19cSWlYSHDa5n+OLjUpq0lBV2ueF90iUblt6aHpg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 '@types/node-fetch': 2.6.2 node-fetch: 3.2.10 dev: false - /@polkadot/x-fetch/10.1.7: - resolution: {integrity: sha512-NL+xrlqUoCLwCIAvQLwOA189gSUgeSGOFjCmZ9uMkBqf35KXeZoHWse6YaoseTSlnAal3dQOGbXnYWZ4Ck2OSA==} + /@polkadot/x-fetch/10.1.2: + resolution: {integrity: sha512-Zd7npq9H/kDaehiM2iyPX1+cSfuhCvqDxuS8GLTjARIVGGURBfA+NjRM6o6jsXa3HCtv+lB67Qdw1m/PSxfIpQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.2 '@types/node-fetch': 2.6.2 node-fetch: 3.2.10 dev: false @@ -3057,7 +3074,7 @@ packages: resolution: {integrity: sha512-qJyLLnm+4SQEZ002UDz2wWnXbnnH84rIS0mLKZ5k82H4lMYY+PQflvzv6sbu463e/lgiEao+6zvWS6DSKv1Yog==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 '@types/node-fetch': 2.6.2 node-fetch: 2.6.7 @@ -3069,7 +3086,7 @@ packages: resolution: {integrity: sha512-ygNparcalYFGbspXtdtZOHvNXZBkNgmNO+um9C0JYq74K5OY9/be93uyfJKJ8JcRJtOqBfVDsJpbiRkuJ1PRfg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 '@types/node-fetch': 2.6.2 node-fetch: 2.6.7 @@ -3084,76 +3101,76 @@ packages: '@babel/runtime': 7.18.9 dev: false - /@polkadot/x-global/10.1.2: - resolution: {integrity: sha512-//r3NVLYdYQs0So0IK8Pa0pnL5pPi0geQWE6qjTtPD0oszuN9SUDqDlFQj3I3vqQOwgybbzBGNYRRinP8B2xUg==} + /@polkadot/x-global/10.1.10: + resolution: {integrity: sha512-WFfgaZSrzPlKLdnOus2mIFGzUbSDIQK6RMCfFfM9SmF3DkoxN40z5Nkni4PztfKr22stlkhmhnX/Lp/NxpuT6Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false - /@polkadot/x-global/10.1.6: - resolution: {integrity: sha512-/nraYZg0hdSjbczhDBAsHlEqeZLs0u0xa8HJrfH2lq8+HOIYkQpJPHOqiQIvEe/VFRq7Xnbij+4uffV+otzB/w==} + /@polkadot/x-global/10.1.2: + resolution: {integrity: sha512-//r3NVLYdYQs0So0IK8Pa0pnL5pPi0geQWE6qjTtPD0oszuN9SUDqDlFQj3I3vqQOwgybbzBGNYRRinP8B2xUg==} engines: {node: '>=14.0.0'} dependencies: '@babel/runtime': 7.18.9 dev: false - /@polkadot/x-global/10.1.7: - resolution: {integrity: sha512-k2ZUZyBVgDnP/Ysxapa0mthn63j6gsN2V0kZejEQPyOfCHtQQkse3jFvAWdslpWoR8j2k8SN5O6reHc0F4f7mA==} + /@polkadot/x-global/10.1.6: + resolution: {integrity: sha512-/nraYZg0hdSjbczhDBAsHlEqeZLs0u0xa8HJrfH2lq8+HOIYkQpJPHOqiQIvEe/VFRq7Xnbij+4uffV+otzB/w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/6.11.1: resolution: {integrity: sha512-lsBK/e4KbjfieyRmnPs7bTiGbP/6EoCZz7rqD/voNS5qsJAaXgB9LR+ilubun9gK/TDpebyxgO+J19OBiQPIRw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/7.9.2: resolution: {integrity: sha512-JX5CrGWckHf1P9xKXq4vQCAuMUbL81l2hOWX7xeP8nv4caHEpmf5T1wD1iMdQBL5PFifo6Pg0V6/oZBB+bts7A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/8.7.1: resolution: {integrity: sha512-WOgUor16IihgNVdiTVGAWksYLUAlqjmODmIK1cuWrLOZtV1VBomWcb3obkO9sh5P6iWziAvCB/i+L0vnTN9ZCA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/9.7.2: resolution: {integrity: sha512-3NN5JhjosaelaFWBJSlv9mb/gDAlt7RuZ8NKlOjB+LQHd9g6ZbnYi5wwjW+i/x/3E4IVbBx66uvWgNaw7IBrkg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false - /@polkadot/x-randomvalues/10.1.2: - resolution: {integrity: sha512-KOu6iZWye9KD6qoahiqZ0alrT/5FSGL4XXLhVSg69xAqD6yG2oi2aKA6cZpDU19uZGqVneqsgpebDsrZ0nLUEg==} + /@polkadot/x-randomvalues/10.1.10: + resolution: {integrity: sha512-KM4sCI/DNLIXlmnkeJIuYvh3pPuWvnkbR1a6TUB12J1izUJ+uGV+cAFRR4/EZk3oEsG/Tgivbs56meEOo3ws5A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 dev: false - /@polkadot/x-randomvalues/10.1.7: - resolution: {integrity: sha512-3er4UYOlozLGgFYWwcbmcFslmO8m82u4cAGR4AaEag0VdV7jLO/M5lTmivT/3rtLSww6sjkEfr522GM2Q5lmFg==} + /@polkadot/x-randomvalues/10.1.2: + resolution: {integrity: sha512-KOu6iZWye9KD6qoahiqZ0alrT/5FSGL4XXLhVSg69xAqD6yG2oi2aKA6cZpDU19uZGqVneqsgpebDsrZ0nLUEg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.2 dev: false /@polkadot/x-randomvalues/6.11.1: resolution: {integrity: sha512-2MfUfGZSOkuPt7GF5OJkPDbl4yORI64SUuKM25EGrJ22o1UyoBnPOClm9eYujLMD6BfDZRM/7bQqqoLW+NuHVw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 dev: false @@ -3161,7 +3178,7 @@ packages: resolution: {integrity: sha512-svQfG31yCXf6yVyIgP0NgCzEy7oc3Lw054ZspkaqjOivxYdrXaf5w3JSSUyM/MRjI2+nk+B/EyJoMYcfSwTfsQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 7.9.2 dev: false @@ -3169,7 +3186,7 @@ packages: resolution: {integrity: sha512-njt17MlfN6yNyNEti7fL12lr5qM6A1aSGkWKVuqzc7XwSBesifJuW4km5u6r2gwhXjH2eHDv9SoQ7WXu8vrrkg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3177,7 +3194,7 @@ packages: resolution: {integrity: sha512-819slnXNpoVtqdhjI19ao7w5m+Zwx11VfwCZkFQypVv3b/1UEoKG/baJA9dVI6yMvhnBN//i8mLgNy3IXWbVVw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false @@ -3185,7 +3202,7 @@ packages: resolution: {integrity: sha512-zIciEmij7SUuXXg9g/683Irx6GogxivrQS2pgBir2DI/YZq+um52+Dqg1mqsEZt74N4KMTMnzAZAP6LJOBOMww==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 rxjs: 6.6.7 dev: false @@ -3197,6 +3214,14 @@ packages: '@polkadot/x-global': 10.1.1 dev: false + /@polkadot/x-textdecoder/10.1.10: + resolution: {integrity: sha512-cAk37faYXx8IICeaq/tdl+aiIXwo3SLrx9XNoQqhX02g+SEs3ARM7zJcohj/p8ynWAI+ezNcsKn1wh174nquHw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 + dev: false + /@polkadot/x-textdecoder/10.1.2: resolution: {integrity: sha512-liMlSSKfLGTvcUPz1fMicH2HoKLgSjzxFYsbNfXJOe9GobQfSrAOcprM0j4gNJqN5EoZhze9Sf1rMTORQwomtg==} engines: {node: '>=14.0.0'} @@ -3209,23 +3234,15 @@ packages: resolution: {integrity: sha512-T+jvyv6OvUgGfOlMDLkPKEmQnZGP1CNohdEDeRr93AmeYikIfbC20qYuAc0bEBXR7/rPXgnqiEfrpkL2W3r/Ig==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 10.1.6 dev: false - /@polkadot/x-textdecoder/10.1.7: - resolution: {integrity: sha512-iAFOHludmZFOyVL8sQFv4TDqbcqQU5gwwYv74duTA+WQBgbSITJrBahSCV/rXOjUqds9pzQO3qBFzziznNnkiQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 - dev: false - /@polkadot/x-textdecoder/6.11.1: resolution: {integrity: sha512-DI1Ym2lyDSS/UhnTT2e9WutukevFZ0WGpzj4eotuG2BTHN3e21uYtYTt24SlyRNMrWJf5+TkZItmZeqs1nwAfQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 dev: false @@ -3233,7 +3250,7 @@ packages: resolution: {integrity: sha512-wfwbSHXPhrOAl12QvlIOGNkMH/N/h8PId2ytIjvM/8zPPFB5Il6DWSFLtVapOGEpIFjEWbd5t8Td4pHBVXIEbg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 7.9.2 dev: false @@ -3241,7 +3258,7 @@ packages: resolution: {integrity: sha512-ia0Ie2zi4VdQdNVD2GE2FZzBMfX//hEL4w546RMJfZM2LqDS674LofHmcyrsv5zscLnnRyCxZC1+J2dt+6MDIA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3249,7 +3266,7 @@ packages: resolution: {integrity: sha512-hhrMNZwJBmusdpqjDRpOHZoMB4hpyJt9Gu9Bi9is7/D/vq/hpxq8z7s6NxrbRyXJf1SIk6NMK0jf5XjRLdKdbw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false @@ -3261,6 +3278,14 @@ packages: '@polkadot/x-global': 10.1.1 dev: false + /@polkadot/x-textencoder/10.1.10: + resolution: {integrity: sha512-Auaql6BL5UHtWakZUQyj4y/BrM0tm4bYG5vXCMQCA1Gg0ky+46DhgpRrAQ9F7NNgWg1A6dA2I9KuAA4BTbNx0w==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 + dev: false + /@polkadot/x-textencoder/10.1.2: resolution: {integrity: sha512-bSMvesZ43Er6+jogt9IfwWN/E8bhkl4a9nNnpyS/vTh+j6n/DfDQrvYpKDpRIn7oJA6lfs/mL9Jo5jjJTngaxg==} engines: {node: '>=14.0.0'} @@ -3273,23 +3298,15 @@ packages: resolution: {integrity: sha512-e+iHdR1P/8xAc54l3gHfqozH6ZfxPkKlVVaz3vOMnzfc8cA3Zw93mLYkGtLDqv+825LkSrWSmb/bDZb6YyEEXg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 10.1.6 dev: false - /@polkadot/x-textencoder/10.1.7: - resolution: {integrity: sha512-GzjaWZDbgzZ0IQT60xuZ7cZ0wnlNVYMqpfI9KvBc58X9dPI3TIMwzbXDVzZzpjY1SAqJGs4hJse9HMWZazfhew==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 - dev: false - /@polkadot/x-textencoder/6.11.1: resolution: {integrity: sha512-8ipjWdEuqFo+R4Nxsc3/WW9CSEiprX4XU91a37ZyRVC4e9R1bmvClrpXmRQLVcAQyhRvG8DKOOtWbz8xM+oXKg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 dev: false @@ -3297,7 +3314,7 @@ packages: resolution: {integrity: sha512-A19wwYINuZwU2dUyQ/mMzB0ISjyfc4cISfL4zCMUAVgj7xVoXMYV2GfjNdMpA8Wsjch3su6pxLbtJ2wU03sRTQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 7.9.2 dev: false @@ -3305,7 +3322,7 @@ packages: resolution: {integrity: sha512-XDO0A27Xy+eJCKSxENroB8Dcnl+UclGG4ZBei+P/BqZ9rsjskUyd2Vsl6peMXAcsxwOE7g0uTvujoGM8jpKOXw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3313,28 +3330,28 @@ packages: resolution: {integrity: sha512-GHbSdbMPixDAOnJ9cvL/x9sPNeHegPoDSqCAzY5H6/zHc/fNn0vUu0To9VpPgPhp/Jb9dbc0h8YqEyvOcOlphw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false - /@polkadot/x-ws/10.1.2: - resolution: {integrity: sha512-RQkc6TPM7xOKHMrE3R/8+FdE9fMGJEN7yfK/GixpMGzw98NcVedxJ1xTL19r76hJvOSeZAEks5oqgMxF8K9Pbg==} + /@polkadot/x-ws/10.1.10: + resolution: {integrity: sha512-JxDgfm0ox2XPAtdTeJXYl6qq7LY/KOPi69wRpFMczWaYUsZubO6EiRzgzjuFlHY4/oxfjS/D+YbzcjefTxHz6g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 '@types/websocket': 1.0.5 websocket: 1.0.34 transitivePeerDependencies: - supports-color dev: false - /@polkadot/x-ws/10.1.7: - resolution: {integrity: sha512-aNkotxHx3qPVjiItD9lbNONs4GNzqeeZ98wHtCjd9JWl/g+xNkOVF3xQ8++1qSHPBEYSwKh9URjQH2+CD2XlvQ==} + /@polkadot/x-ws/10.1.2: + resolution: {integrity: sha512-RQkc6TPM7xOKHMrE3R/8+FdE9fMGJEN7yfK/GixpMGzw98NcVedxJ1xTL19r76hJvOSeZAEks5oqgMxF8K9Pbg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.2 '@types/websocket': 1.0.5 websocket: 1.0.34 transitivePeerDependencies: @@ -3345,7 +3362,7 @@ packages: resolution: {integrity: sha512-GNu4ywrMlVi0QF6QSpKwYWMK6JRK+kadgN/zEhMoH1z5h8LwpqDLv128j5WspWbQti2teCQtridjf7t2Lzoe8Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 '@types/websocket': 1.0.5 websocket: 1.0.34 @@ -3357,7 +3374,7 @@ packages: resolution: {integrity: sha512-Mt0tcNzGXyKnN3DQ06alkv+JLtTfXWu6zSypFrrKHSQe3u79xMQ1nSicmpT3gWLhIa8YF+8CYJXMrqaXgCnDhw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 '@types/websocket': 1.0.5 websocket: 1.0.34 @@ -3460,7 +3477,7 @@ packages: /@subsocial/definitions/0.6.11: resolution: {integrity: sha512-FQDzZmSaHXQ9x5HoudPcDYf3BmH2CN7zPbPZS+01LZXhelDN7qbNk36+pBeXki0zmtUnevWjy6LKld8zZ3XLBw==} dependencies: - '@polkadot/api': 9.3.3 + '@polkadot/api': 9.4.3 lodash.camelcase: 4.3.0 transitivePeerDependencies: - bufferutil @@ -3482,11 +3499,11 @@ packages: - supports-color dev: false - /@substrate/connect/0.7.11: - resolution: {integrity: sha512-/xiOlkmJfl2XPYQTmyWKEh2AXryEAPSMAxZXs6D/aqYDy0TKZDAp1dfQiHyPt1vMwOlnM4WJv9lPks3ZMwCP+w==} + /@substrate/connect/0.7.14: + resolution: {integrity: sha512-uW5uBmihpivshmmmw+rsg7qOV0KqVSep4rWOXFMP8aFQinvmqw4JqxP21og4H/7JZxttYUBFQVsdtXHGKJ0aVQ==} dependencies: '@substrate/connect-extension-protocol': 1.0.1 - '@substrate/smoldot-light': 0.6.30 + '@substrate/smoldot-light': 0.6.34 eventemitter3: 4.0.7 transitivePeerDependencies: - bufferutil @@ -3511,8 +3528,8 @@ packages: - supports-color dev: false - /@substrate/smoldot-light/0.6.30: - resolution: {integrity: sha512-U/F75XzxuNG+KGSujxsMAm8zUBpBON+l0oX19EnSWjvqD+smYjvcj1SeqQhFYxJjtoCQyZLedKBsZGyNbG3FbQ==} + /@substrate/smoldot-light/0.6.34: + resolution: {integrity: sha512-+HK9MaJ0HelJmpf4YYR+salJ7dhVBltmhGlyz5l8OXS9DW18fe0Z2wxEo8P5kX9CUxlCXEb8J9JBRQAYBPHbwQ==} dependencies: pako: 2.0.4 ws: 8.8.1 @@ -3535,8 +3552,8 @@ packages: resolution: {integrity: sha512-LmCH4QJRdHaeLsLTPSgJaXguMoIW+Ig9fA9LRPpeya9HefVAJ7gZuUYinldv+QmX7evNm5CL0rspNUS8l1DvXg==} dev: false - /@substrate/ss58-registry/1.28.0: - resolution: {integrity: sha512-XPSwSq4CThLyg+OnZ5/LHh3SPDQjRdGS3Ux5ClgWhRCQamlU86FCT1LBwQ/i+ximbdBfqKRRzVhm1ql3AJ9FKQ==} + /@substrate/ss58-registry/1.31.0: + resolution: {integrity: sha512-OSOmdjaq9foXfHBy9aLVMwGheygvsiZlv4dggnLOYOuhSmNCsSB/PaW4DBz+/tSdK1Fo9+ZiFW6cF24RA+m0sw==} dev: false /@substrate/txwrapper-core/3.1.7: @@ -8039,6 +8056,12 @@ packages: dependencies: tslib: 2.4.0 + /rxjs/7.5.7: + resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} + dependencies: + tslib: 2.4.0 + dev: false + /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} diff --git a/src/subscriptions/subscriptions.service.spec.ts b/src/subscriptions/subscriptions.service.spec.ts index 4df6153..5f660db 100644 --- a/src/subscriptions/subscriptions.service.spec.ts +++ b/src/subscriptions/subscriptions.service.spec.ts @@ -58,14 +58,17 @@ describe('subscriptionsService', () => { }) describe('onModuleInit', () => { - it('should show an error message', async () => { + it('should show an error message', () => { try { - jest.spyOn(service, 'syncBlocks').mockResolvedValue(Promise.reject('grcp error')) + jest.spyOn(service, 'syncBlocks').mockImplementation(() => { + throw new Error('grcp error') + }) - await service.onModuleInit() + service.onModuleInit() fail("Shouldn't reach this point") } catch (error) { - expect(error).toBe('grcp error') + console.log(error) + expect((error as Error).message).toBe('grcp error') } }) }) diff --git a/src/subscriptions/subscriptions.service.ts b/src/subscriptions/subscriptions.service.ts index af30cb6..14eb6da 100644 --- a/src/subscriptions/subscriptions.service.ts +++ b/src/subscriptions/subscriptions.service.ts @@ -26,10 +26,10 @@ export class SubscriptionsService implements OnModuleInit { private readonly eventsService: EventsService, ) {} - async onModuleInit(): Promise { + onModuleInit(): void { try { this.logger.info('Subscribing to new heads...') - await this.syncBlocks() + this.syncBlocks() } catch (error) { this.logger.error({ error }, 'Error while processing blocks.') throw error From 3375e6a5da17c4bcde648654f400de6f5f339755 Mon Sep 17 00:00:00 2001 From: Fernando Sirni <33009762+fersirni@users.noreply.github.com> Date: Mon, 10 Oct 2022 15:15:01 -0300 Subject: [PATCH 02/28] Updating polkadot api version (#7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change skipped test (#2) * fixes * fix documentation * fix images folder Co-authored-by: Fernando Sirni * [Snyk] Security upgrade node from 16.15-alpine to 16.16.0-alpine (#4) fix: Dockerfile to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946427 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946428 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946723 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946727 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946729 * [Snyk] Security upgrade node from 16.15-alpine to 16.16.0-alpine (#3) fix: dev.Dockerfile to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946427 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946428 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946723 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946727 - https://snyk.io/vuln/SNYK-UPSTREAM-NODE-2946729 * Update docs (#5) * Update docs * Update spanish docs * Update CHANGELOG.md * Review/env fix (#6) * README.md fix * env.sample fix * updating polkadot api * adding timestamp Co-authored-by: José Co-authored-by: Ruben Gutierrez <45153592+RubenGutierrezC@users.noreply.github.com> Co-authored-by: Snyk bot --- .env.sample | 4 +- .github/workflows/pr.yaml | 14 +- .images/graphql_example.png | Bin 0 -> 124913 bytes .images/pg_admin_connection.png | Bin 0 -> 39219 bytes .images/pg_admin_select_server.png | Bin 0 -> 14004 bytes .images/pg_admin_server_name.png | Bin 0 -> 38190 bytes .images/pg_admin_up.png | Bin 0 -> 28318 bytes CHANGELOG.md | 9 + CONTRIBUTING.md | 31 + Dockerfile | 4 +- README-es.md | 247 ++--- README.md | 249 ++--- dev.Dockerfile | 2 +- docker-compose.yaml | 11 +- mocks/blocks-mocks.ts | 1 + mocks/events-mocks.ts | 16 +- mocks/transactions-mock.ts | 5 + package.json | 16 +- pnpm-lock.yaml | 851 +++++++++--------- src/blocks/blocks.service.spec.ts | 4 + src/blocks/blocks.service.ts | 3 +- src/blocks/entity/block.entity.ts | 6 +- src/events/entity/event.entity.ts | 6 +- src/events/events.service.spec.ts | 18 +- src/events/events.service.ts | 2 + src/schema.graphql | 3 + .../subscriptions.service.spec.ts | 14 +- src/subscriptions/subscriptions.service.ts | 20 +- src/transactions/entity/transaction.entity.ts | 6 +- src/transactions/transactions.service.spec.ts | 14 +- src/transactions/transactions.service.ts | 2 + 31 files changed, 888 insertions(+), 670 deletions(-) create mode 100644 .images/graphql_example.png create mode 100644 .images/pg_admin_connection.png create mode 100644 .images/pg_admin_select_server.png create mode 100644 .images/pg_admin_server_name.png create mode 100644 .images/pg_admin_up.png create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md diff --git a/.env.sample b/.env.sample index d90258b..ef1581a 100644 --- a/.env.sample +++ b/.env.sample @@ -1,5 +1,5 @@ -NODE_ENV=development -PORT=8080 +NODE_ENV=production +PORT=5000 LOG_NAME=ink-substrate-explorer-api LOG_LEVEL=debug diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 40484c9..b60bba3 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -2,9 +2,12 @@ name: Pulll Request App Build # Controls when the action will run. on: - # Triggers the workflow pull request events but only for the main and develop branch + # Triggers the workflow pull request events pull_request: - branches: [main, develop, staging] + branches: ['**'] + # Triggers the workflow push events but only for the main + push: + branches: [main] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -59,4 +62,9 @@ jobs: # run: pnpm test:e2e - name: Build source code. - run: pnpm build \ No newline at end of file + run: pnpm build + + - name: Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.images/graphql_example.png b/.images/graphql_example.png new file mode 100644 index 0000000000000000000000000000000000000000..a20540eecd1815b7c4e45ba0be44f0b6711f84be GIT binary patch literal 124913 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˟>lU&5pH;i;NOKIaLBi?0rj5eqs_r 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

41%qW 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 Ubo}6fW(FYeboFyt=akR{0QXeX@c;k- literal 0 HcmV?d00001 diff --git a/.images/pg_admin_connection.png b/.images/pg_admin_connection.png new file mode 100644 index 0000000000000000000000000000000000000000..9fb24f896e0ce4b1a1e1e91c64937bed3ac4c86c GIT binary patch literal 39219 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

j*feQ_O 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 literal 0 HcmV?d00001 diff --git a/.images/pg_admin_server_name.png b/.images/pg_admin_server_name.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d2e4a996040835aa6132f3799f8519e9d6e7be GIT binary patch literal 38190 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 LwZK*K=Ar)uz9fhv literal 0 HcmV?d00001 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5a62c0e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## 1.0.0 +Published by **[blockcoders](https://github.com/blockcoders)** on **2022/09/28** +- [#5](https://github.com/blockcoders/ink-substrate-explorer-api/pull/5) Update docs +- [#4](https://github.com/blockcoders/ink-substrate-explorer-api/pull/4) [Snyk] Security upgrade node from 16.15-alpine to 16.16.0-alpine +- [#3](https://github.com/blockcoders/ink-substrate-explorer-api/pull/3) [Snyk] Security upgrade node from 16.15-alpine to 16.16.0-alpine +- [#2](https://github.com/blockcoders/ink-substrate-explorer-api/pull/2) Change skipped test +- [#1](https://github.com/blockcoders/ink-substrate-explorer-api/pull/1) Milestone 1 Ink Explorer API diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..feec3d0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,31 @@ +# Contributing + +1. [Fork it](https://help.github.com/articles/fork-a-repo/) +2. Install dependencies (`pnpm i --frozen-lockfile`) +3. Create your feature branch (`git checkout -b my-new-feature`) +4. Commit your changes (`git commit -am 'Added some feature'`) +5. Test your changes (`pnpm test`) +6. Push to the branch (`git push origin my-new-feature`) +7. [Create new Pull Request](https://help.github.com/articles/creating-a-pull-request/) + +## Testing + +We use [Jest](https://github.com/facebook/jest) to write tests. Run our test suite with this command: + +``` +pnpm test +``` + +## Code Style + +We use [Prettier](https://prettier.io/) and tslint to maintain code style and best practices. +Please make sure your PR adheres to the guides by running: + +``` +pnpm format +``` + +and +``` +pnpm lint +``` \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 29c7cb2..20c689f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16.15-alpine AS builder +FROM node:16.16.0-alpine AS builder # Create app directory WORKDIR /usr/src/app @@ -23,7 +23,7 @@ RUN pnpm prune --prod --no-optional # By using the FROM statement again, we are telling Docker that it should create a new, # fresh image without any connection to the previous one. -FROM node:16.15-alpine AS build +FROM node:16.16.0-alpine AS build # Create app directory WORKDIR /usr/src/app diff --git a/README-es.md b/README-es.md index 5766c42..2395a50 100644 --- a/README-es.md +++ b/README-es.md @@ -1,4 +1,9 @@ -# **Ink! Explorer** +Ink! Explorer API +================= + +[![App Build](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml/badge.svg)](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml) +[![Coverage Status](https://coveralls.io/repos/github/blockcoders/ink-substrate-explorer-api/badge.svg?branch=main)](https://coveralls.io/github/blockcoders/ink-substrate-explorer-api?branch=main) +[![Known Vulnerabilities](https://snyk.io/test/github/blockcoders/ink-substrate-explorer-api/badge.svg)](https://snyk.io/test/github/blockcoders/ink-substrate-explorer-api) ## **Acerca del explorador** @@ -8,47 +13,6 @@ La idea de este proyecto es brindar una herramienta que permita a los desarrolla Este proyecto ofrece información útil que no está disponible en ningún otro lugar. Ya que el back end se encarga de obtener información relacionada con los saldos, transacciones y más, de los contratos que utilizan módulos Ink!. El explorador utiliza polkadot.js para comunicarse con las redes Substrate/Polkadot. Es seguro decir que este proyecto es imprescindible. -Blockcoders es un equipo que siempre está contribuyendo a los proyectos de blockchain para ayudar al crecimiento del ecosistema. - -## **Sobre nosotros** - -### Miembros del equipo - -- Jose Ramirez -- Fernando Sirni -- Ruben Gutierrez - -### Contacto - -- **Nombre de contacto:** Jose Ramirez -- **Email de contacto:** jose@blockcoders.io -- **Sitio web:** http://blockcoders.io/ - -### Experiencia del equipo - -Nuestro equipo ha estado contribuyendo con diferentes proyectos en blockchain durante algunos años, construyendo API, SDK y herramientas para desarrolladores. Nuestro objetivo es continuar impulsando el mundo crypto invirtiendo capital intelectual en proyectos, participando activamente para ayudar a dar forma a los ecosistemas en los que creemos. - -### Repositorios del equipo - -- https://github.com/blockcoders -- https://github.com/blockcoders/nestjs-ethers -- https://github.com/blockcoders/harmony-marketplace-sdk -- https://github.com/blockcoders/near-rpc-providers -- https://github.com/athenafarm/athena-vault-contracts -- https://github.com/athenafarm/athena-sdk - -### Githubs de los miembros del equipo - -- https://github.com/0xslipk -- https://github.com/fersirni -- https://github.com/RubenGutierrezC - -### Perfiles de linkedIn de los miembros del equipo - -- https://www.linkedin.com/in/jarcodallo/ -- https://www.linkedin.com/in/fernando-sirni-1931ba122/ -- https://www.linkedin.com/in/rubengutierrezc/ - ## **Introduccion** ## Levantando el servicio localmente @@ -62,7 +26,7 @@ Nuestro equipo ha estado contribuyendo con diferentes proyectos en blockchain du ### Instalar todas las dependencias -``` +```sh pnpm i --frozen-lockfile ``` @@ -70,57 +34,91 @@ pnpm i --frozen-lockfile **Nota**: El archivo .env tiene la configuracion para GraphQL, la base de datos PostgreSQL, Node y la url del RPC de la blockchain basada en Substrate. -``` +```sh cp .env.sample .env ``` - **Configuraciones del servicio** - -- **NODE_ENV**=development -- **PORT**=8080 -- **LOG_NAME**=ink-substrate-explorer-api -- **LOG_LEVEL**=debug +#### Configuraciones del servicio - **Configuraciones de GraphQL** +```sh +NODE_ENV=development +PORT=8080 +LOG_NAME=ink-substrate-explorer-api +LOG_LEVEL=debug +``` -- **GRAPHQL_DEBUG**=true -- **GRAPHQL_PLAYGROUND**=true -- **GRAPHQL_SORT_SCHEMA**=true -- **GRAPHQL_INTROSPECTION**=true +#### Configuraciones de GraphQL - **Configuraciones de la base de datos** +```sh +GRAPHQL_DEBUG=true +GRAPHQL_PLAYGROUND=true +GRAPHQL_SORT_SCHEMA=true +GRAPHQL_INTROSPECTION=true +``` -- **DATABASE_HOST**=postgres -- **DATABASE_NAME**=ink -- **DATABASE_USERNAME**=root -- **DATABASE_PASSWORD**=password -- **DATABASE_RETRY_ATTEMPTS**=5 -- **DATABASE_RETRY_DELAY**=3000 +#### Configuraciones de la base de datos - **Configuraciones de la blockchain y la sincronizacion de datos** +```sh +DATABASE_HOST=postgres +DATABASE_NAME=ink +DATABASE_USERNAME=root +DATABASE_PASSWORD=password +DATABASE_RETRY_ATTEMPTS=5 +DATABASE_RETRY_DELAY=3000 +``` -- **WS_PROVIDER**=wss://rococo-contracts-rpc.polkadot.io -- **LOAD_ALL_BLOCKS**=false - Asignar el valor _true_ para procesar cada bloque desde FIRST_BLOCK_TO_LOAD hasta el ultimo bloque de la cadena. Asignar el valor _false_ para solo comenzar a procesar los bloques desde el ultimo bloque existente en la base de datos. +#### Configuraciones de la blockchain y la sincronizacion de datos -- **FIRST_BLOCK_TO_LOAD**=0 - Número de bloque a partir del cual el servicio comenzará a procesar bloques. (Puede ser génesis o algún otro bloque. Por ejemplo, el primer bloque admite contratos) +```sh +WS_PROVIDER=wss://rococo-contracts-rpc.polkadot.io +# Asignar el valor _true_ para procesar cada bloque desde FIRST_BLOCK_TO_LOAD hasta el ultimo bloque de la cadena. Asignar el valor _false_ para solo comenzar a procesar los bloques desde el ultimo bloque existente en la base de datos. +LOAD_ALL_BLOCKS=false +# Número de bloque a partir del cual el servicio comenzará a procesar bloques. (Puede ser génesis o algún otro bloque. Por ejemplo, el primer bloque admite contratos) +FIRST_BLOCK_TO_LOAD=0 +# Número de bloques a procesar simultáneamente. Esto puede acelerar o retrasar el proceso de sincronización. +BLOCK_CONCURRENCY=1000 +``` -- **BLOCK_CONCURRENCY**=1000 - Número de bloques a procesar simultáneamente. Esto puede acelerar o retrasar el proceso de sincronización. +## **Levantando el servicio (DEV)** ### Instanciar una BD Postgres utilizando docker (opcional) Para levantar el servicio es necesario contar con una **BD PostgreSQL**. Para esto, el archivo **dev-docker-compose.yaml** ya tiene una imagen configurada lista para usar. Ejecutando el siguiente comando tambien instanciara un contenedor para pgAdmin: -``` +```sh docker-compose -f dev-docker-compose.yaml up -d ``` +Una vez que el servicio se está ejecutando, se puede acceder a pgAdmin siguiendo el enlace que se muestra en la terminal (en este caso localhost:80). + +![pgAdmin](/.images/pg_admin_up.png) + +Las credenciales para acceder a pgAdmin son (establecidas en el archivo dev-docker-compose): + +- PGADMIN_DEFAULT_EMAIL: "admin@admin.com" +- PGADMIN_DEFAULT_PASSWORD: "admin" + +Registre un nuevo servidor en pgAdmin y establezca las credenciales para la base de datos PostgreSQL: + +Haga clic derecho en 'Servidores' y seleccione "Registrarse" -> "Servidor" + +![pgAdmin](/.images/pg_admin_select_server.png) + +Establezca un nombre para el servidor (en este ejemplo, "Docker") + +![pgAdmin](/.images/pg_admin_server_name.png) + +Establezca las credenciales para la base de datos PostgreSQL (esto se puede encontrar en el archivo dev-docker-compose): + +![pgAdmin](/.images/pg_admin_connection.png) + ### Instanciar un nodo local de Substrate (opcional) El servicio necesita conectarse a una blockchain basada en Substrate. Para esto, el archivo **dev-docker-compose.yaml** ya tiene una imagen configurada lista para usar. Ejecute este comando: -``` +```sh docker-compose -f dev-docker-compose.yaml up -d ``` @@ -128,59 +126,85 @@ Otra forma de ejecutar un nodo local es con [esta guía de paritytech](https://g **Nota**: Cambie la variable WS_PROVIDER en el archivo **.env** para que sea `ws://127.0.0.1:9944` -### Levantando el servicio (DEV) +### Levantando el servicio -- ### `pnpm start:dev` +```sh +pnpm start:dev +``` Ejecuta el servicio en el modo de desarrollo. El servicio se recargará si realiza ediciones. **Nota**: Se requiere una base de datos postgres en funcionamiento y una conexión válida a un nodo de Substrate. -### Levantando el servicio (PROD) +## **Levantando el servicio (PROD)** -Para iniciar tanto el contenedor del servicio de back-end como el contenedor de la base de datos, ejecute: +Para iniciar los contenedores del servicio de backend, la BD y pgAdmin ejecutar el siguiente comando: -- ### `docker-compose up -d` - -### Test - -Ejecución de las pruebas unitarias. - -- ### `pnpm test` - -Ejecución de la cobertura de pruebas. - -- ### `pnpm test:cov` +```sh +docker-compose up -d +``` +**Nota**: Se requiere una base de datos postgres en funcionamiento y una conexión válida a un nodo de Substrate. +Opcionalmente, comente el servicio de back-end en el archivo docker-compose si desea ejecutar la imagen localmente. ## Ejecutar la imagen de Docker del servicio back-end ### Descarga la imagen de DockerHub -``` +```sh docker pull blockcoders/ink-substrate-explorer-api:latest ``` ### Run -- ### `docker run -it -p 5000:5000 --network ink-explorer-network --env-file {pathToEnvFile} blockcoders/ink-substrate-explorer-api:latest` - -Verifique que la imagen comenzó a ejecutarse +```sh +# Crear la red de docker +docker network create ink-explorer-network +# Correr servicio +docker run -it -p 5000:5000 --network ink-explorer-network --env-file {pathToEnvFile} blockcoders/ink-substrate-explorer-api:latest ``` + +#### Verifique que la imagen comenzó a ejecutarse + +```sh docker ps ``` El resultado debería verse así: -``` +```sh CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f31a7d0fd6c8 blockcoders/ink-substrate-explorer-api "docker-entrypoint.s…" 15 seconds ago Up 14 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp funny_lumiere ``` -Después de que se inició el servidor, los bloques deberían guardarse en la base de datos. +El servicio se conectará al contenedor DB y comenzará a procesar bloques. + +## **Testing** + +Ejecución de las pruebas unitarias. + +```sh +pnpm test +``` + +Ejecución de la cobertura de pruebas. + +```sh +pnpm test:cov +``` + +Probando las consultas de GraphQL. + +```sh +{"level":30,"time":1664298430389,"pid":1388770,"hostname":"username","name":"ink-substrate-explorer-api","msg":"App listening on http://0.0.0.0:5000"} +``` + +Una vez que el servicio back-end se está ejecutando, se puede acceder a GraphQL Playground en http://localhost:5000/graphql -## **API** +![backend](/.images/graphql_example.png) + +## **Definicion de la API** Una vez que el servicio esta levantado y corriendo correctamente se provee una API que puede utilizarse enviado consultas de GraphQL. @@ -402,7 +426,7 @@ query { ```graphql query { - decodeEvents(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") + decodeEvents(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") } ``` @@ -446,7 +470,10 @@ query { ```graphql mutation Upload { - uploadMetadata(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc", metadata: "ewogICJzb3VyY2UiOiB7CiAgICAiaGFzaCI6I...(base64)") + uploadMetadata( + contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc" + metadata: "ewogICJzb3VyY2UiOiB7CiAgICAiaGFzaCI6I...(base64)" + ) } ``` @@ -609,15 +636,33 @@ En caso de un tiempo de inactividad del nodo, las suscripciones se reconectarán ### Algunos puntos de referencia #### Utilizando BLOCK_CONCURRENCY = 100 -- 100 bloques en ~ 6 segundos -- 1000 bloques en ~ 30.5 segundos -- 10000 bloques en ~ 4:24 minutos -- 100000 bloques en ~ 39.57 minutos + +- 100 bloques en ~ 6 segundos +- 1000 bloques en ~ 30.5 segundos +- 10000 bloques en ~ 4:24 minutos +- 100000 bloques en ~ 39.57 minutos #### Utilizando BLOCK_CONCURRENCY = 1000 -- 100 bloques en ~ 0.5 segundos -- 1000 bloques en ~ 5 segundos -- 10000 bloques en ~ 3 minutos -- 100000 bloques en ~ 24 minutos +- 100 bloques en ~ 0.5 segundos +- 1000 bloques en ~ 5 segundos +- 10000 bloques en ~ 3 minutos +- 100000 bloques en ~ 24 minutos + +## Registro de cambios + +Consulte [Changelog](CHANGELOG.md) para más información. + +## Contribuye + +¡Las contribuciones son bienvenidas! Consulte [Contributing](CONTRIBUTING.md). + +## Colaboradores + +* [__Jose Ramirez__](https://github.com/0xslipk) +* [__Fernando Sirni__](https://github.com/fersirni) +* [__Ruben Gutierrez__](https://github.com/RubenGutierrezC) + +## Licencia +Con licencia de Apache 2.0 - consulte el archivo [LICENSE](LICENSE) para obtener más información. diff --git a/README.md b/README.md index 3725abc..d089f99 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# **Ink! Explorer** +Ink! Explorer API +================= + +[![App Build](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml/badge.svg)](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml) +[![Coverage Status](https://coveralls.io/repos/github/blockcoders/ink-substrate-explorer-api/badge.svg?branch=main)](https://coveralls.io/github/blockcoders/ink-substrate-explorer-api?branch=main) +[![Known Vulnerabilities](https://snyk.io/test/github/blockcoders/ink-substrate-explorer-api/badge.svg)](https://snyk.io/test/github/blockcoders/ink-substrate-explorer-api) ## **About the explorer** @@ -8,47 +13,6 @@ The idea of this project is to provide a tool that allows developers of Ink! exp This project serves useful information that is not available anywhere else. Since the back end is in charge of obtaining information related to the balances, transactions and more, of the contracts that use Ink modules. Ink Explorer uses polkadot.js to communicate with the Substrate / Polkadot networks. It is safe to say that this project is a must. -Blockcoders is a team that is always contributing to blockchain projects to help the growth of the ecosystem. - -## **About us** - -### Team members - -- Jose Ramirez -- Fernando Sirni -- Ruben Gutierrez - -### Contact - -- **Contact Name:** Jose Ramirez -- **Contact Email:** jose@blockcoders.io -- **Website:** http://blockcoders.io/ - -### Team's experience - -Our team has been contributing with different projects in blockchain for a few years, building APIs, SDKs and developer tools. Our goal is to continue to drive the crypto space forward by investing intellectual capital into projects, participating actively to help shape the ecosystems we believe in. - -### Team Code Repos - -- https://github.com/blockcoders -- https://github.com/blockcoders/nestjs-ethers -- https://github.com/blockcoders/harmony-marketplace-sdk -- https://github.com/blockcoders/near-rpc-providers -- https://github.com/athenafarm/athena-vault-contracts -- https://github.com/athenafarm/athena-sdk - -### Team personal Githubs - -- https://github.com/0xslipk -- https://github.com/fersirni -- https://github.com/RubenGutierrezC - -### Team LinkedIn Profiles - -- https://www.linkedin.com/in/jarcodallo/ -- https://www.linkedin.com/in/fernando-sirni-1931ba122/ -- https://www.linkedin.com/in/rubengutierrezc/ - ## **Get Started** ## Running the service locally @@ -62,7 +26,7 @@ Our team has been contributing with different projects in blockchain for a few y ### Install all the dependencies -``` +```sh pnpm i --frozen-lockfile ``` @@ -70,57 +34,91 @@ pnpm i --frozen-lockfile **Note**: The .env file has the configuration for GraphQL, the PostgreSQL database, Node and the RPC url of the Substrate Blockchain. -``` +```sh cp .env.sample .env ``` - **Service configurations** - -- **NODE_ENV**=development -- **PORT**=8080 -- **LOG_NAME**=ink-substrate-explorer-api -- **LOG_LEVEL**=debug +#### Service configurations - **GraphQL configurations** +```sh +NODE_ENV=development +PORT=8080 +LOG_NAME=ink-substrate-explorer-api +LOG_LEVEL=debug +``` -- **GRAPHQL_DEBUG**=true -- **GRAPHQL_PLAYGROUND**=true -- **GRAPHQL_SORT_SCHEMA**=true -- **GRAPHQL_INTROSPECTION**=true +#### GraphQL configurations - **Database configurations** +```sh +GRAPHQL_DEBUG=true +GRAPHQL_PLAYGROUND=true +GRAPHQL_SORT_SCHEMA=true +GRAPHQL_INTROSPECTION=true +``` -- **DATABASE_HOST**=postgres -- **DATABASE_NAME**=ink -- **DATABASE_USERNAME**=root -- **DATABASE_PASSWORD**=password -- **DATABASE_RETRY_ATTEMPTS**=5 -- **DATABASE_RETRY_DELAY**=3000 +#### Database configurations - **Blockchain and Sync configurations** +```sh +DATABASE_HOST=postgres +DATABASE_NAME=ink +DATABASE_USERNAME=root +DATABASE_PASSWORD=password +DATABASE_RETRY_ATTEMPTS=5 +DATABASE_RETRY_DELAY=3000 +``` -- **WS_PROVIDER**=wss://rococo-contracts-rpc.polkadot.io -- **LOAD_ALL_BLOCKS**=false - Set to _true_ to process every block from FIRST_BLOCK_TO_LOAD to the current block. Set to _false_ to only start processing blocks from the last existing block in the database. +#### Blockchain and Sync configurations -- **FIRST_BLOCK_TO_LOAD**=0 - Block number from which the service will start to process blocks. (Can be genesis or some other block. For example, the first block supporting contracts) +```sh +WS_PROVIDER=wss://rococo-contracts-rpc.polkadot.io +# Set to true to process every block from FIRST_BLOCK_TO_LOAD to the current block. Set to false to only start processing blocks from the last existing block in the database. +LOAD_ALL_BLOCKS=false +# Block number from which the service will start to process blocks. (Can be genesis or some other block. For example, the first block supporting contracts) +FIRST_BLOCK_TO_LOAD=0 +# Number of blocks to process concurrently. This can speed up or down the syncing process. +BLOCK_CONCURRENCY=1000 +``` -- **BLOCK_CONCURRENCY**=1000 - Number of blocks to process concurrently. This can speed up or down the syncing process. +## **Starting the project (DEV)** ### Start a Postgres DB using docker (optional) To start the project a **PostgreSQL DB** is needed. For that, the **dev-docker-compose.yaml** file already has an image set up ready to use. Running this command it will also start a container for pgAdmin: -``` +```sh docker-compose -f dev-docker-compose.yaml up -d ``` +Once the service is running, pgAdmin can be accessed following the link that is shown in the terminal (In this case localhost:80). + +![pgAdmin](/.images/pg_admin_up.png) + +The credentials to access pgAdmin are (set in the dev-docker-compose file): + +- PGADMIN_DEFAULT_EMAIL: "admin@admin.com" +- PGADMIN_DEFAULT_PASSWORD: "admin" + +Register a new server in pgAdmin and set the credentials for the PostgreSQL DB: + +Right click on 'Servers' and select "Register" -> "Server" + +![pgAdmin](/.images/pg_admin_select_server.png) + +Set a name for the server (In this example "Docker") + +![pgAdmin](/.images/pg_admin_server_name.png) + +Set the credentials for the PostgreSQL DB (this can be found in the dev-docker-compose file): + +![pgAdmin](/.images/pg_admin_connection.png) + ### Start a local Substrate Node (optional) The service needs to connect to a Substrate Blockchain. For that, the **dev-docker-compose.yaml** file already has an image set up ready to use. Run this command: -``` +```sh docker-compose -f dev-docker-compose.yaml up -d ``` @@ -128,59 +126,85 @@ Another way to run a local node is with [this paritytech guide](https://github.c **Note**: Change the WS_PROVIDER var in the **.env** file to be `ws://127.0.0.1:9944` -### Starting the project (DEV) +### Start the service -- ### `pnpm start:dev` +```sh +pnpm start:dev +``` Runs the service in the development mode. The service will reload if you make edits. **Note**: A postgresDB up and running and a valid connection to a substrate node are required. -### Starting the project (PROD) +## **Starting the project (PROD)** -To start both the Back-end service container and the DB container run: +To start the backend service, DB and pgAdmin containers run the following command: -- ### `docker-compose up -d` - -### Test - -Running the unit tests. - -- ### `pnpm test` - -Running the test coverage. - -- ### `pnpm test:cov` +```sh +docker-compose up -d +``` +**Note**: A postgresDB up and running and a valid connection to a substrate node are required. +Optionally comment the backend service in the docker-compose file if you want to run the image locally. ## Running the Back-end service Docker image ### Download the image from DockerHub -``` +```sh docker pull blockcoders/ink-substrate-explorer-api:latest ``` ### Run -- ### `docker run -it -p 5000:5000 --network ink-explorer-network --env-file {pathToEnvFile} blockcoders/ink-substrate-explorer-api:latest` - -Verify the image started running +```sh +# Create a docker network +docker network create ink-explorer-network +# Run the service +docker run -it -p 5000:5000 --network ink-explorer-network --env-file {pathToEnvFile} blockcoders/ink-substrate-explorer-api:latest ``` + +#### Verify the image started running + +```sh docker ps ``` The result should look like this: -``` +```sh CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f31a7d0fd6c8 blockcoders/ink-substrate-explorer-api "docker-entrypoint.s…" 15 seconds ago Up 14 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp funny_lumiere ``` -After the server started, the blocks should be being saved on the DB. +The service will connect to the DB container and start processing blocks. + +## **Testing** + +Running the unit tests. + +```sh +pnpm test +``` + +Running the test coverage. + +```sh +pnpm test:cov +``` + +Testing the GraphQL queries. + +```sh +{"level":30,"time":1664298430389,"pid":1388770,"hostname":"username","name":"ink-substrate-explorer-api","msg":"App listening on http://0.0.0.0:5000"} +``` + +Once the back-end service is running, the GraphQL Playground can be accessed at http://localhost:5000/graphql -## **API** +![backend](/.images/graphql_example.png) + +## **API definition** With the service up and running an API is provided by using GraphQL queries. @@ -402,7 +426,7 @@ query { ```graphql query { - decodeEvents(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") + decodeEvents(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") } ``` @@ -446,7 +470,10 @@ query { ```graphql mutation Upload { - uploadMetadata(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc", metadata: "ewogICJzb3VyY2UiOiB7CiAgICAiaGFzaCI6I...(base64)") + uploadMetadata( + contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc" + metadata: "ewogICJzb3VyY2UiOiB7CiAgICAiaGFzaCI6I...(base64)" + ) } ``` @@ -604,20 +631,38 @@ The first time the node is started, it may need to start from the block 0 and lo In case of a downtime of the node, the subscriptions will be reconnected automatically recovering all new blocks from the last block that was processed. -**Note**: Load all blocks may take a long time depending on the number of blocks that need to be loaded. It is recommended to use a node with a fast internet connection. The node will be able to process all blocks in a few hours. +**Note**: Load all blocks may take a long time depending on the number of blocks that need to be loaded. It is recommended to use a node with a fast internet connection. The node will be able to process all blocks in a few hours. ### Some benchmarks #### Using BLOCK_CONCURRENCY = 100 -- 100 blocks ~ 6 seconds -- 1000 blocks ~ 30.5 seconds -- 10000 blocks ~ 4:24 minutes -- 100000 blocks ~ 39.57 minutes + +- 100 blocks ~ 6 seconds +- 1000 blocks ~ 30.5 seconds +- 10000 blocks ~ 4:24 minutes +- 100000 blocks ~ 39.57 minutes #### Using BLOCK_CONCURRENCY = 1000 -- 100 blocks ~ 0.5 seconds -- 1000 blocks ~ 5 seconds -- 10000 blocks ~ 3 minutes -- 100000 blocks ~ 24 minutes +- 100 blocks ~ 0.5 seconds +- 1000 blocks ~ 5 seconds +- 10000 blocks ~ 3 minutes +- 100000 blocks ~ 24 minutes + +## Change Log + +See [Changelog](CHANGELOG.md) for more information. + +## Contributing + +Contributions welcome! See [Contributing](CONTRIBUTING.md). + +## Collaborators + +* [__Jose Ramirez__](https://github.com/0xslipk) +* [__Fernando Sirni__](https://github.com/fersirni) +* [__Ruben Gutierrez__](https://github.com/RubenGutierrezC) + +## License +Licensed under the Apache 2.0 - see the [LICENSE](LICENSE) file for details. diff --git a/dev.Dockerfile b/dev.Dockerfile index 7e14c99..6e572f6 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -1,4 +1,4 @@ -FROM node:16.15-alpine +FROM node:16.16.0-alpine # Create app directory WORKDIR /usr/src/app diff --git a/docker-compose.yaml b/docker-compose.yaml index e785251..770c9b0 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,9 @@ version: '3.7' networks: ink-explorer-network: + name: ink-explorer-network + default: + driver: ink-explorer-network services: backend: @@ -18,7 +21,7 @@ services: - /usr/src/app/node_modules - /usr/src/app/dist networks: - ink-explorer-network: + ink-explorer-network: aliases: - "backend" env_file: @@ -33,7 +36,7 @@ services: - POSTGRES_PASSWORD=password - POSTGRES_DB=ink networks: - ink-explorer-network: + ink-explorer-network: aliases: - "postgres" pgadmin: @@ -46,6 +49,6 @@ services: depends_on: - postgres networks: - ink-explorer-network: + ink-explorer-network: aliases: - - "pgadmin" \ No newline at end of file + - "pgadmin" diff --git a/mocks/blocks-mocks.ts b/mocks/blocks-mocks.ts index 18d0a86..4d726c2 100644 --- a/mocks/blocks-mocks.ts +++ b/mocks/blocks-mocks.ts @@ -2,6 +2,7 @@ export const mockBlock = { hash: '0x03b26a67c6c7fda467f7b96d09b99d04ef9a8163043e72b5e5474358631afad2', parentHash: '0x9b0f818b9cac7d9451819de6172e308d67c4b8ff8c2f1f6773cdb20c40573858', number: 27, + timestamp: 1590000000, createdDate: '2022-08-25 22:49:21.843575', } diff --git a/mocks/events-mocks.ts b/mocks/events-mocks.ts index 44357f5..2c33382 100644 --- a/mocks/events-mocks.ts +++ b/mocks/events-mocks.ts @@ -9,10 +9,10 @@ export const mockEvents = [ method: 'ContractEmitted', topics: '[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x33766995fd9b44bd45f351b3abd7e5041960638db0075c84ab7af1a734e20d1b, 0x5445726332303a3a5472616e736665723a3a66726f6d00000000000000000000]', - data: `[ - "5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9", - "0x000001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d0000c52ebca2b1000000000000000000" - ]`, + data: [ + '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', + '0x000001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d0000c52ebca2b1000000000000000000', + ], createdDate: '2022-08-31 20:03:28.568881', contractAddress: '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', }, @@ -24,10 +24,10 @@ export const mockEvents = [ method: 'ContractEmitted', topics: '[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x63c87cd1c4007df77d6b16ae28c5393bee3a62fb8577e38243a6f6f5a82c457f, 0xda2d695d3b5a304e0039e7fc4419c34fa0c1f239189c99bb72a6484f1634782b]', - data: `[ - "5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9", - "0x0001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e0040e59c301200000000000000000000" - ]`, + data: [ + '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', + '0x0001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e0040e59c301200000000000000000000', + ], createdDate: '2022-08-31 20:03:38.814484', contractAddress: '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', }, diff --git a/mocks/transactions-mock.ts b/mocks/transactions-mock.ts index 7e25327..3184498 100644 --- a/mocks/transactions-mock.ts +++ b/mocks/transactions-mock.ts @@ -11,6 +11,7 @@ export const mockTransaction = { signer: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', nonce: 37, tip: 0, + timestamp: 1600000000000, createdDate: '2022-08-25 23:42:49.006343', } @@ -41,6 +42,8 @@ export const mockTransactions = [ }, ] +export const mockTimestamp = 1600000000000 + export const mockExtrinsics = [ { hash: stringToHex('0x01c780fccc47dc4e9652180876a8267dc9f9dd501ed249f077e32c1653a89f2a'), @@ -57,6 +60,7 @@ export const mockExtrinsics = [ method: { method: 'set', section: 'timestamp', + args: [mockTimestamp], }, }, { @@ -74,6 +78,7 @@ export const mockExtrinsics = [ method: { method: 'call', section: 'timestamp', + args: [mockTimestamp], }, }, ] diff --git a/package.json b/package.json index 7c02803..d7a9ca9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ink-substrate-explorer-api", - "version": "1.0.0-alpha.1", + "version": "1.0.1", "description": "Ink Explorer is an application that provides Ink contracts related information on Substrate based blockchains.", "author": "Blockcoders ", "license": "MIT", @@ -19,7 +19,7 @@ "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", - "start:prod": "node dist/src/main", + "start:prod": "NODE_ENV=production node dist/src/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "lint:ci": "eslint \"{src,apps,libs,test}/**/*.ts\"", "test": "jest", @@ -93,12 +93,12 @@ "@nestjs/mapped-types": "1.1.0", "@nestjs/platform-fastify": "8.4.7", "@nestjs/typeorm": "9.0.0", - "@polkadot/api": "^8.14.1", - "@polkadot/api-augment": "^8.14.1", - "@polkadot/api-contract": "^8.14.1", - "@polkadot/types": "^8.14.1", - "@polkadot/types-codec": "^8.14.1", - "@polkadot/types-create": "^8.14.1", + "@polkadot/api": "^9.4.3", + "@polkadot/api-augment": "^9.4.3", + "@polkadot/api-contract": "^9.4.3", + "@polkadot/types": "^9.4.3", + "@polkadot/types-codec": "^9.4.3", + "@polkadot/types-create": "^9.4.3", "@polkadot/util": "10.1.2", "@substrate/txwrapper": "^7.0.1", "@substrate/txwrapper-core": "^3.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e48f59..0d5b8e1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,12 +15,12 @@ specifiers: '@nestjs/schematics': ^8.0.11 '@nestjs/testing': ^8.4.7 '@nestjs/typeorm': 9.0.0 - '@polkadot/api': ^8.14.1 - '@polkadot/api-augment': ^8.14.1 - '@polkadot/api-contract': ^8.14.1 - '@polkadot/types': ^8.14.1 - '@polkadot/types-codec': ^8.14.1 - '@polkadot/types-create': ^8.14.1 + '@polkadot/api': ^9.4.3 + '@polkadot/api-augment': ^9.4.3 + '@polkadot/api-contract': ^9.4.3 + '@polkadot/types': ^9.4.3 + '@polkadot/types-codec': ^9.4.3 + '@polkadot/types-create': ^9.4.3 '@polkadot/util': 10.1.2 '@substrate/txwrapper': ^7.0.1 '@substrate/txwrapper-core': ^3.1.7 @@ -78,12 +78,12 @@ dependencies: '@nestjs/mapped-types': 1.1.0_7zw7e46jhcfuw5vwuwho2brjki '@nestjs/platform-fastify': 8.4.7_7tsmhnugyerf5okgqzer2mfqme '@nestjs/typeorm': 9.0.0_zhrs42futwpjx7z3p6twpp4g7i - '@polkadot/api': 8.14.1 - '@polkadot/api-augment': 8.14.1 - '@polkadot/api-contract': 8.14.1 - '@polkadot/types': 8.14.1 - '@polkadot/types-codec': 8.14.1 - '@polkadot/types-create': 8.14.1 + '@polkadot/api': 9.4.3 + '@polkadot/api-augment': 9.4.3 + '@polkadot/api-contract': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 '@polkadot/util': 10.1.2 '@substrate/txwrapper': 7.0.1 '@substrate/txwrapper-core': 3.1.7 @@ -654,6 +654,13 @@ packages: regenerator-runtime: 0.13.9 dev: false + /@babel/runtime/7.19.0: + resolution: {integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.9 + dev: false + /@babel/template/7.18.10: resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} engines: {node: '>=6.9.0'} @@ -1521,6 +1528,10 @@ packages: resolution: {integrity: sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==} dev: false + /@noble/hashes/1.1.3: + resolution: {integrity: sha512-CE0FCR57H2acVI5UOzIGSSIYxZ6v/HOhDR0Ro9VLyhnzLwx0o8W1mmgaqlEUx4049qJDlIBRztv5k+MM8vbO3A==} + dev: false + /@noble/secp256k1/1.5.5: resolution: {integrity: sha512-sZ1W6gQzYnu45wPrWx8D3kwI2/U29VYTx9OjbDAd7jwRItJ0cSTMPRL/C8AWZFn9kWFLQGqEXVEE86w4Z8LpIQ==} dev: false @@ -1533,6 +1544,10 @@ packages: resolution: {integrity: sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==} dev: false + /@noble/secp256k1/1.7.0: + resolution: {integrity: sha512-kbacwGSsH/CTout0ZnZWxnW1B+jH/7r/WAAKLBtrRJ/+CUH7lgmQzl3GTrQua3SGKWNSDsS6lmjnDpIJ5Dxyaw==} + dev: false + /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1592,7 +1607,7 @@ packages: resolution: {integrity: sha512-7csQLS6zuYuGq7W1EkTBz1ZmxyRvx/Qpz7E7zPSwxmY8Whb7Yn2effU9XF0eCcRpyfSW8LodF8wMmLxGYs1OaQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-base': 7.15.1 '@polkadot/rpc-augment': 7.15.1 '@polkadot/types': 7.15.1 @@ -1608,28 +1623,28 @@ packages: resolution: {integrity: sha512-65GMlgVnZd08Ifh8uAj+p/+MlXxvsAfBcCHjQhOmbCE0dki+rzTPUR31LsWyDKtuw+nUBj0iZN4PelO+wU4r0g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-base': 8.14.1 '@polkadot/rpc-augment': 8.14.1 '@polkadot/types': 8.14.1 '@polkadot/types-augment': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - supports-color dev: false - /@polkadot/api-augment/9.3.3: - resolution: {integrity: sha512-usO5G2lDjzmwrPCgpe9IS5J2gddrDfeuWECc9/ruw35/ag4x8uZkiViC9762pF9fu9ZzNfSrk2QRnVGRcbG1ZQ==} + /@polkadot/api-augment/9.4.3: + resolution: {integrity: sha512-w1iAdfpHprQiPkk9s98vRFqf9AJ70GoheGAEqO6p7JKYoutPlA8Pg8NiacwiCWW464zdbRn/T2/fWGtn8Iv27A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api-base': 9.3.3 - '@polkadot/rpc-augment': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-augment': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/api-base': 9.4.3 + '@polkadot/rpc-augment': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-augment': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - bufferutil - supports-color @@ -1640,11 +1655,11 @@ packages: resolution: {integrity: sha512-UlhLdljJPDwGpm5FxOjvJNFTxXMRFaMuVNx6EklbuetbBEJ/Amihhtj0EJRodxQwtZ4ZtPKYKt+g+Dn7OJJh4g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 7.15.1 '@polkadot/types': 7.15.1 '@polkadot/util': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -1654,51 +1669,53 @@ packages: resolution: {integrity: sha512-EXFhNXIfpirf18IsqcG2pGQW1/Xn+bfjqVYQMMJ4ZONtYH4baZZlXk7SoXCCHonN2x1ixs4DOcRx5oVxjabdIQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 8.14.1 '@polkadot/types': 8.14.1 - '@polkadot/util': 10.1.6 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - supports-color dev: false - /@polkadot/api-base/9.3.3: - resolution: {integrity: sha512-MFjcdwNyqKxoWkqSJRkMtaQogFxsCW6HBVowT0lUrQ2WzTLBWQqi7DcC/0RsRQXXN/SsUwczi3g9b12wqLZLhg==} + /@polkadot/api-base/9.4.3: + resolution: {integrity: sha512-gYzf7LIcKo/rEGlXgoMOS619srcTmyD7wwZ9b0xh/Xg0vHPyUi8OVs3i4SRQrXS8KSVuZzBCrqALPytXmV0xdg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/util': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate dev: false - /@polkadot/api-contract/8.14.1: - resolution: {integrity: sha512-ZIdlSoN5WktQD/Q97cg7MuRcQsFe+4RZDXLew2uUg2R1IyEon+TzEGPXUPVAEQuhlOyRxT6f4/UEM/yTdoGPSQ==} + /@polkadot/api-contract/9.4.3: + resolution: {integrity: sha512-PnBZyUgaLf7DGHkfrRrYISGRXLpZXykJj3L6KKcMrZL7MgiPvyhYzNVXCTmhGOjPQxhaYUDk8VPWmArLf8qT2Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api': 8.14.1 - '@polkadot/types': 8.14.1 - '@polkadot/types-codec': 8.14.1 - '@polkadot/types-create': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/api': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: + - bufferutil - supports-color + - utf-8-validate dev: false /@polkadot/api-derive/4.17.1: resolution: {integrity: sha512-mgq57F1yAiZjuiA0vrR2zWidyyd+mGe7Kbs4SxVeDWLsNbLc9+eASIfX7Hch2SDHIn3CQpv6DQqJH00uDfw9Lw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api': 4.17.1 '@polkadot/rpc-core': 4.17.1 '@polkadot/types': 4.17.1 @@ -1714,7 +1731,7 @@ packages: resolution: {integrity: sha512-CsOQppksQBaa34L1fWRzmfQQpoEBwfH0yTTQxgj3h7rFYGVPxEKGeFjo1+IgI2vXXvOO73Z8E4H/MnbxvKrs1Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api': 7.15.1 '@polkadot/api-augment': 7.15.1 '@polkadot/api-base': 7.15.1 @@ -1723,7 +1740,7 @@ packages: '@polkadot/types-codec': 7.15.1 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -1733,34 +1750,34 @@ packages: resolution: {integrity: sha512-eWG1MrQhHMUjt9gDHN9/9/ZMATu1MolqcalPFhNoGtdON3+I0J3ntjQ4y5X7+p2OGwQplpYRKqbK4k7tKzu8tA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api': 8.14.1 '@polkadot/api-augment': 8.14.1 '@polkadot/api-base': 8.14.1 '@polkadot/rpc-core': 8.14.1 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - supports-color dev: false - /@polkadot/api-derive/9.3.3: - resolution: {integrity: sha512-UiIEKJ0YttgrAqikK/sH0CxedZMijoM33Fuyr4mNWe7srb5MewoABdnwzUMmRVDLjrKA18gtOfSNhqEDliRYGw==} + /@polkadot/api-derive/9.4.3: + resolution: {integrity: sha512-6lKjJs93ucSF/mmljG32TcWq4gg35MimbuXxDYwNYXwuGm6ocN0auWp6Opg+DGLuwapfHhkOyZxSBVWi37gjEQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api': 9.3.3 - '@polkadot/api-augment': 9.3.3 - '@polkadot/api-base': 9.3.3 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/api': 9.4.3 + '@polkadot/api-augment': 9.4.3 + '@polkadot/api-base': 9.4.3 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color @@ -1771,7 +1788,7 @@ packages: resolution: {integrity: sha512-uuNIKWC+PjM+1AARRu4NLWOEudZE6DW8UOlaubx3uGhPywqPIP+HGWP2I6PqRGYKARBWxxOvca1Q7WoKzpYC8w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-derive': 4.17.1 '@polkadot/keyring': 6.11.1 '@polkadot/metadata': 4.17.1 @@ -1792,7 +1809,7 @@ packages: resolution: {integrity: sha512-z0z6+k8+R9ixRMWzfsYrNDnqSV5zHKmyhTCL0I7+1I081V18MJTCFUKubrh0t1gD0/FCt3U9Ibvr4IbtukYLrQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-augment': 7.15.1 '@polkadot/api-base': 7.15.1 '@polkadot/api-derive': 7.15.1 @@ -1808,7 +1825,7 @@ packages: '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 eventemitter3: 4.0.7 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -1818,7 +1835,7 @@ packages: resolution: {integrity: sha512-jg26eIKFYqVfDBTAopHL3aDaNw9j6TdUkXuvYJOnynpecU4xwbTVKcOtSOjJ2eRX4MgMQ4zlyMHJx3iKw0uUTA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/api-augment': 8.14.1 '@polkadot/api-base': 8.14.1 '@polkadot/api-derive': 8.14.1 @@ -1831,7 +1848,7 @@ packages: '@polkadot/types-codec': 8.14.1 '@polkadot/types-create': 8.14.1 '@polkadot/types-known': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 '@polkadot/util-crypto': 10.1.2 eventemitter3: 4.0.7 rxjs: 7.5.6 @@ -1839,27 +1856,27 @@ packages: - supports-color dev: false - /@polkadot/api/9.3.3: - resolution: {integrity: sha512-esOfwnKS/6JRL0C8TDqYn4GC9GkWp8vTdKIWLuncW2jEtiJLYccb5IVngfOQImVrqAQoV1hJdLnj9X6k+tGqQQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/api-augment': 9.3.3 - '@polkadot/api-base': 9.3.3 - '@polkadot/api-derive': 9.3.3 - '@polkadot/keyring': 10.1.7 - '@polkadot/rpc-augment': 9.3.3 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/rpc-provider': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-augment': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/types-create': 9.3.3 - '@polkadot/types-known': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 + /@polkadot/api/9.4.3: + resolution: {integrity: sha512-vbeWW2tyntAmWllUqnOwlaprFT+5o8a0uP0Qkz5QfLslUFZtxhHhLWtQWVtJnoqC5FN10ZybDkUGFlsxNsvwgg==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/api-augment': 9.4.3 + '@polkadot/api-base': 9.4.3 + '@polkadot/api-derive': 9.4.3 + '@polkadot/keyring': 10.1.10 + '@polkadot/rpc-augment': 9.4.3 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/rpc-provider': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-augment': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/types-known': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 eventemitter3: 4.0.7 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color @@ -1913,29 +1930,29 @@ packages: - utf-8-validate dev: false - /@polkadot/keyring/10.1.2: - resolution: {integrity: sha512-b6hP3JFGYjsNNT3NO7I8fWRPqovgL4IvjvLttkfzpM6eM1zRRupqQ+Q50Jdl/3YUcr26PcxQcdRqJku4WyDABg==} + /@polkadot/keyring/10.1.10: + resolution: {integrity: sha512-crKYBbwmPcFoTP6mby2+o1QWsjAyi5QlKzU8tXuXOApP6SBuqmDujIuLOKNG2vZoftNdVldsVL0WmKVYtBeuQg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 - '@polkadot/util-crypto': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 dev: false - /@polkadot/keyring/10.1.7: - resolution: {integrity: sha512-lArwaAS3hDs+HHupDIC4r2mFaAfmNQV2YzwL2wM5zhOqB2RugN03BFrgwNll0y9/Bg8rYDqM3Y5BvVMzgMZ6XA==} + /@polkadot/keyring/10.1.2: + resolution: {integrity: sha512-b6hP3JFGYjsNNT3NO7I8fWRPqovgL4IvjvLttkfzpM6eM1zRRupqQ+Q50Jdl/3YUcr26PcxQcdRqJku4WyDABg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 + '@polkadot/util-crypto': 10.1.2 dev: false /@polkadot/keyring/6.11.1: resolution: {integrity: sha512-rW8INl7pO6Dmaffd6Df1yAYCRWa2RmWQ0LGfJeA/M6seVIkI6J3opZqAd4q2Op+h9a7z4TESQGk8yggOEL+Csg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 '@polkadot/util-crypto': 6.11.1 dev: false @@ -1944,7 +1961,7 @@ packages: resolution: {integrity: sha512-6UGoIxhiTyISkYEZhUbCPpgVxaneIfb/DBVlHtbvaABc8Mqh1KuqcTIq19Mh9wXlBuijl25rw4lUASrE/9sBqg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 '@polkadot/util-crypto': 7.9.2 dev: false @@ -1953,7 +1970,7 @@ packages: resolution: {integrity: sha512-t6ZgQVC+nQT7XwbWtEhkDpiAzxKVJw8Xd/gWdww6xIrawHu7jo3SGB4QNdPgkf8TvDHYAAJiupzVQYAlOIq3GA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 dev: false @@ -1962,7 +1979,7 @@ packages: resolution: {integrity: sha512-219isiCWVfbu5JxZnOPj+cV4T+S0XHS4+Jal3t3xz9y4nbgr+25Pa4KInEsJPx0u8EZAxMeiUCX3vd5U7oe72g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 4.17.1 '@polkadot/types-known': 4.17.1 '@polkadot/util': 6.11.1 @@ -1978,43 +1995,43 @@ packages: '@substrate/ss58-registry': 1.25.0 dev: false - /@polkadot/networks/10.1.2: - resolution: {integrity: sha512-67ZPqdhLYDGNX1jMEa3+hujh9j30Dr9AdqgdjE8Z3GdWoEVRp9Zda3DXMnDIQlRBQ32pRZty7dFhIq61Bv/whQ==} + /@polkadot/networks/10.1.10: + resolution: {integrity: sha512-Db78t2XnFIZbdSdu1aFuj3/1cNwcSzG/+wNrpCQ9dPhnGPy5S1GVbmU8pyxTftPKdTFc+8RdBr+5bc0d5ijGiA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 - '@substrate/ss58-registry': 1.25.0 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@substrate/ss58-registry': 1.31.0 dev: false - /@polkadot/networks/10.1.7: - resolution: {integrity: sha512-ol864SZ/GwAF72GQOPRy+Y9r6NtgJJjMBlDLESvV5VK64eEB0MRSSyiOdd7y/4SumR9crrrNimx3ynACFgxZ8A==} + /@polkadot/networks/10.1.2: + resolution: {integrity: sha512-67ZPqdhLYDGNX1jMEa3+hujh9j30Dr9AdqgdjE8Z3GdWoEVRp9Zda3DXMnDIQlRBQ32pRZty7dFhIq61Bv/whQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@substrate/ss58-registry': 1.28.0 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 + '@substrate/ss58-registry': 1.25.0 dev: false /@polkadot/networks/6.11.1: resolution: {integrity: sha512-0C6Ha2kvr42se3Gevx6UhHzv3KnPHML0N73Amjwvdr4y0HLZ1Nfw+vcm5yqpz5gpiehqz97XqFrsPRauYdcksQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/networks/7.9.2: resolution: {integrity: sha512-4obI1RdW5/7TFwbwKA9oqw8aggVZ65JAUvIFMd2YmMC2T4+NiZLnok0WhRkhZkUnqjLIHXYNwq7Ho1i39dte0g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/networks/8.7.1: resolution: {integrity: sha512-8xAmhDW0ry5EKcEjp6VTuwoTm0DdDo/zHsmx88P6sVL87gupuFsL+B6TrsYLl8GcaqxujwrOlKB+CKTUg7qFKg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 '@substrate/ss58-registry': 1.25.0 dev: false @@ -2023,7 +2040,7 @@ packages: resolution: {integrity: sha512-oMAdF8Y9CLBI0EUZBcycHcvbQQdbkJHevPJ/lwnZXJTaueXuav/Xm2yiFj5J3V8meIjLocURlMawgsAVItXOBQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@substrate/ss58-registry': 1.25.0 dev: false @@ -2032,7 +2049,7 @@ packages: resolution: {integrity: sha512-sK0+mphN7nGz/eNPsshVi0qd0+N0Pqxuebwc1YkUGP0f9EkDxzSGp6UjGcSwWVaAtk9WZZ1MpK1Jwb/2GrKV7Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 7.15.1 '@polkadot/types': 7.15.1 '@polkadot/types-codec': 7.15.1 @@ -2046,24 +2063,24 @@ packages: resolution: {integrity: sha512-0dIsNVIMeCp0kV7+Obz0Odt6K32Ka2ygwhiV5jhhJthy8GJBPo94mKDed5gzln3Dgl2LEdJJt1h/pgCx4a2i4A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-core': 8.14.1 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - supports-color dev: false - /@polkadot/rpc-augment/9.3.3: - resolution: {integrity: sha512-xU+Fc1gm3C0CvFl2+38LN5qAdyw4ECSj2qxTymro6jqnHxpiyCvRtMg5Grl3MzREVFwhthg80W19jT1hjdPhyg==} + /@polkadot/rpc-augment/9.4.3: + resolution: {integrity: sha512-j4oFAPfP+AyQVb1rl8Jbj5k0UqfZyHUy0+CLHtu/Q0S9Wk0R1SDPACpI+93H0DjwYAFfsxbRMhloAH1IJWD5uA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/rpc-core': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/rpc-core': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 transitivePeerDependencies: - bufferutil - supports-color @@ -2074,7 +2091,7 @@ packages: resolution: {integrity: sha512-1gqYaYuSSQsRmt3ol55jmjBP/euKyAh4PwSj94I2wu0fngK/FZwVZNDJZn/Ib68X/s38TBIgqJ6+YdUdr3z1xw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/metadata': 4.17.1 '@polkadot/rpc-provider': 4.17.1 '@polkadot/types': 4.17.1 @@ -2089,12 +2106,12 @@ packages: resolution: {integrity: sha512-4Sb0e0PWmarCOizzxQAE1NQSr5z0n+hdkrq3+aPohGu9Rh4PodG+OWeIBy7Ov/3GgdhNQyBLG+RiVtliXecM3g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-augment': 7.15.1 '@polkadot/rpc-provider': 7.15.1 '@polkadot/types': 7.15.1 '@polkadot/util': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 transitivePeerDependencies: - encoding - supports-color @@ -2104,26 +2121,26 @@ packages: resolution: {integrity: sha512-deQ8Ob59ao/1fZQdaVtFjYR/HCBdxSYvQGt7/alBu1Uig9Sahx9oKcMkU5rWY36XqGZYos4zLay98W2hDlf+6Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/rpc-augment': 8.14.1 '@polkadot/rpc-provider': 8.14.1 '@polkadot/types': 8.14.1 - '@polkadot/util': 10.1.6 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - supports-color dev: false - /@polkadot/rpc-core/9.3.3: - resolution: {integrity: sha512-KMT98HeYt6IpFvTRKWhFkHxQvGhuVIT0gyOjvT+hmuDQqt3k3bcgoQSR7218uD51NNYhnZJpjAKl3LTJz2Fdgg==} + /@polkadot/rpc-core/9.4.3: + resolution: {integrity: sha512-xTU33bNnqdLaaCFdGnoxY03rmmgUKH/2JoEa+fBRvt9RPc7KuanWSKSeHieekZXSgCXBJ3zbfStyo43klg74OQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/rpc-augment': 9.3.3 - '@polkadot/rpc-provider': 9.3.3 - '@polkadot/types': 9.3.3 - '@polkadot/util': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/rpc-augment': 9.4.3 + '@polkadot/rpc-provider': 9.4.3 + '@polkadot/types': 9.4.3 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 transitivePeerDependencies: - bufferutil - supports-color @@ -2134,7 +2151,7 @@ packages: resolution: {integrity: sha512-vlU1H5mnfP0Ej8PbjcxwF9ZlT7LtcpekOKI4iYfMnfdelSUKUVyaD5PC8yRGIg9fxkorA6OM5AZs116jAl3TLA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 4.17.1 '@polkadot/util': 6.11.1 '@polkadot/util-crypto': 6.11.1 @@ -2151,7 +2168,7 @@ packages: resolution: {integrity: sha512-n0RWfSaD/r90JXeJkKry1aGZwJeBUUiMpXUQ9Uvp6DYBbYEDs0fKtWLpdT3PdFrMbe5y3kwQmNLxwe6iF4+mzg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 8.7.1 '@polkadot/types': 7.15.1 '@polkadot/types-support': 7.15.1 @@ -2173,12 +2190,12 @@ packages: resolution: {integrity: sha512-pAUSHZiSWLhBSYf4LmLc8iCaeqTu7Ajn8AzyqxvZDHGnIrzV5M7eTjpNDP84qno6jWRHKQ/IILr62hausEmS5w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 10.1.2 '@polkadot/types': 8.14.1 '@polkadot/types-support': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 '@polkadot/x-fetch': 10.1.2 '@polkadot/x-global': 10.1.6 '@polkadot/x-ws': 10.1.2 @@ -2190,20 +2207,20 @@ packages: - supports-color dev: false - /@polkadot/rpc-provider/9.3.3: - resolution: {integrity: sha512-A5eX5WfG5JeYXUNRBOEGtSqvmQN6jqbrAmXkufSWYvGb/1Ip2l/9oHuUjswGLdpaWfOkpVkClyCXIFtWx06XNw==} + /@polkadot/rpc-provider/9.4.3: + resolution: {integrity: sha512-8HCkwlDnH6Y6WNT0Yg8e6YM5Wk+GacnO906nhtHByR2MRL8ugvLRb0x97PSPrR+NYs+ecYUURFkRy0fujuFcHQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/keyring': 10.1.7 - '@polkadot/types': 9.3.3 - '@polkadot/types-support': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 - '@polkadot/x-fetch': 10.1.7 - '@polkadot/x-global': 10.1.7 - '@polkadot/x-ws': 10.1.7 - '@substrate/connect': 0.7.11 + '@babel/runtime': 7.19.0 + '@polkadot/keyring': 10.1.10 + '@polkadot/types': 9.4.3 + '@polkadot/types-support': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + '@polkadot/x-fetch': 10.1.10 + '@polkadot/x-global': 10.1.10 + '@polkadot/x-ws': 10.1.10 + '@substrate/connect': 0.7.14 eventemitter3: 4.0.7 mock-socket: 9.1.5 nock: 13.2.9 @@ -2217,7 +2234,7 @@ packages: resolution: {integrity: sha512-aqm7xT/66TCna0I2utpIekoquKo0K5pnkA/7WDzZ6gyD8he2h0IXfe8xWjVmuyhjxrT/C/7X1aUF2Z0xlOCwzQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 7.15.1 '@polkadot/types-codec': 7.15.1 '@polkadot/util': 8.7.1 @@ -2227,27 +2244,27 @@ packages: resolution: {integrity: sha512-Xa4TUFqyZT+IJ6pBSwDjWcF42u/E34OyC+gbs5Z2vWQ4EzSDkq4xNoUKjJlEEgTemsD9lhPOIc4jvqTCefwxEw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-augment/9.3.3: - resolution: {integrity: sha512-XAhyX5DEYnsMunpoU1podjm5ODosTmMwwpNcUK95ALcyzkpstyWIjUW3JhaEOzIshsYmJUNxM7/cSI4jv/VLAg==} + /@polkadot/types-augment/9.4.3: + resolution: {integrity: sha512-TvN3vhUVylFyWGHHXOO4/iHIFW6EXHLBlIBC7YhUQc0dZOD+mKjnNblEtDY/GazlwBQjq9bhXcoH0S6KIpiSIg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types-codec/7.15.1: resolution: {integrity: sha512-nI11dT7FGaeDd/fKPD8iJRFGhosOJoyjhZ0gLFFDlKCaD3AcGBRTTY8HFJpP/5QXXhZzfZsD93fVKrosnegU0Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false @@ -2255,25 +2272,25 @@ packages: resolution: {integrity: sha512-y6YDN4HwvEgSWlgrEV04QBBxDxES1cTuUQFzZJzOTuZCWpA371Mdj3M9wYxGXMnj0wa+rCQGECHPZZaNxBMiKg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.6 - '@polkadot/x-bigint': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/x-bigint': 10.1.10 dev: false - /@polkadot/types-codec/9.3.3: - resolution: {integrity: sha512-DiSGZ/pwZO0huS4CnyI0Z4nsvKSFUAjjcVQ7lt1BqCRcUFoIZtYQgzXftia1kSXnJs4J13PMcFTfQZeTDnp4Sg==} + /@polkadot/types-codec/9.4.3: + resolution: {integrity: sha512-x0BJZxcPyollDx9urF7rAfDdKHZXe150p9op2if8fw02LNTDGGsrWLw7DD8ISNwXbtL8L+N1ipc0mVqfsHg+Aw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/x-bigint': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/x-bigint': 10.1.10 dev: false /@polkadot/types-create/7.15.1: resolution: {integrity: sha512-+HiaHn7XOwP0kv/rVdORlVkNuMoxuvt+jd67A/CeEreJiXqRLu+S61Mdk7wi6719PTaOal1hTDFfyGrtUd8FSQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types-codec': 7.15.1 '@polkadot/util': 8.7.1 dev: false @@ -2282,25 +2299,25 @@ packages: resolution: {integrity: sha512-fb9yyblj5AYAPzeCIq0kYSfzDxRDi/0ud9gN2UzB3H7M/O4n2mPC1vD4UOLF+B7l9QzCrt4e+k+/riGp7GfvyA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types-codec': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-create/9.3.3: - resolution: {integrity: sha512-LRS5sWYtPyXZ8AC7j9foFQQzYhay2q4YnXD9Hfz2ULrjtpjdUgR0hP3GpBKfxDnlWESpzGjegSAIDs+z/sKnfA==} + /@polkadot/types-create/9.4.3: + resolution: {integrity: sha512-kx5Yccp/I4RrtbOo3+iFJSVDwbl0Y9Xm0B4p7khYkKUHAbNuuFZMMnnMru2hOTWDgpQPN6Fbixt9pdy4TD6Xnw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/types-codec': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/types-codec': 9.4.3 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types-known/4.17.1: resolution: {integrity: sha512-YkOwGrO+k9aVrBR8FgYHnfJKhOfpdgC5ZRYNL/xJ9oa7lBYqPts9ENAxeBmJS/5IGeDF9f32MNyrCP2umeCXWg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 6.11.1 '@polkadot/types': 4.17.1 '@polkadot/util': 6.11.1 @@ -2310,7 +2327,7 @@ packages: resolution: {integrity: sha512-Z8bHpPQy+mqUm0uR1tai6ra0bQIoPmgRcGFYUM+rJtW1kx/6kZLh10HAICjLpPeA1cwLRzaxHRDqH5MCU6OgXw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 8.7.1 '@polkadot/types': 6.12.1 '@polkadot/util': 8.7.1 @@ -2320,7 +2337,7 @@ packages: resolution: {integrity: sha512-LMcNP0CxT84DqAKV62/qDeeIVIJCR5yzE9b+9AsYhyfhE4apwxjrThqZA7K0CF56bOdQJSexAerYB/jwk2IijA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 8.7.1 '@polkadot/types': 7.15.1 '@polkadot/types-codec': 7.15.1 @@ -2332,31 +2349,31 @@ packages: resolution: {integrity: sha512-GP7gRo9nmitykkrRnoLF61Qm19UFdTwMsOnJkdm7AOeWDmZGxutacgO6k1tBsHr38hsiCCGsB/JiseUgywvGIw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 10.1.2 '@polkadot/types': 8.14.1 '@polkadot/types-codec': 8.14.1 '@polkadot/types-create': 8.14.1 - '@polkadot/util': 10.1.6 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-known/9.3.3: - resolution: {integrity: sha512-TcDGzHpPZdMxrywLHTbjaHaFRdJdFaL5QGpvcSeDwAGHz7zU6Aq29AT9HwJ8GrBNihLALUj79S1/D2WfmJuXFA==} + /@polkadot/types-known/9.4.3: + resolution: {integrity: sha512-JoIC31If1tLhz4ykNCcJCJGEuufJo7c880vCDLzdYn/OCxxHvdrUeNAFZu0ua/QNHNpT7Pl24NGUrE2QfmZbRg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/networks': 10.1.7 - '@polkadot/types': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/types-create': 9.3.3 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/networks': 10.1.10 + '@polkadot/types': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types-support/7.15.1: resolution: {integrity: sha512-FIK251ffVo+NaUXLlaJeB5OvT7idDd3uxaoBM6IwsS87rzt2CcWMyCbu0uX89AHZUhSviVx7xaBxfkGEqMePWA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false @@ -2364,23 +2381,23 @@ packages: resolution: {integrity: sha512-XqR4qq6pCZyNBuFVod8nFSNUmLssrjoU9bOIn4Ua2cqNlI9xsuKaI1X5ySEn/oWOtKQ2L5hbCm9vkXrEtXBl1w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.6 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-support/9.3.3: - resolution: {integrity: sha512-KJeL3bBc8XEIDuUFjYLBunAvMkVi8LXdln4V1FPHEt6OgXkbqJlc9KAwgrPUaV1+Ki0LIBDDYKtUiMG3c9Ip+g==} + /@polkadot/types-support/9.4.3: + resolution: {integrity: sha512-PCIHVj40A5qgUQJHOM4BpeVwXPVNo0PNeVVWMPPLdnUMr3hX8dqCjZnWAUizgTICJ5EutCLL5wKP6/JBZmmWsA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false /@polkadot/types/4.17.1: resolution: {integrity: sha512-rjW4OFdwvFekzN3ATLibC2JPSd8AWt5YepJhmuCPdwH26r3zB8bEC6dM7YQExLVUmygVPvgXk5ffHI6RAdXBMg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/metadata': 4.17.1 '@polkadot/util': 6.11.1 '@polkadot/util-crypto': 6.11.1 @@ -2391,84 +2408,84 @@ packages: resolution: {integrity: sha512-O37cAGUL0xiXTuO3ySweVh0OuFUD6asrd0TfuzGsEp3jAISWdElEHV5QDiftWq8J9Vf8BMgTcP2QLFbmSusxqA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/types-known': 6.12.1 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 dev: false /@polkadot/types/7.15.1: resolution: {integrity: sha512-KawZVS+eLR1D6O7c/P5cSUwr6biM9Qd2KwKtJIO8l1Mrxp7r+y2tQnXSSXVAd6XPdb3wVMhnIID+NW3W99TAnQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 8.7.1 '@polkadot/types-augment': 7.15.1 '@polkadot/types-codec': 7.15.1 '@polkadot/types-create': 7.15.1 '@polkadot/util': 8.7.1 '@polkadot/util-crypto': 8.7.1 - rxjs: 7.5.6 + rxjs: 7.5.7 dev: false /@polkadot/types/8.14.1: resolution: {integrity: sha512-Xza16ejKrSd4XhTOlbfISyxZ2sRmbMAZk5pX7VEMHVZHqV98o+bJ2f9Kk7F8YJijkHHGosCLDestP9R5nLoOoA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/keyring': 10.1.2 '@polkadot/types-augment': 8.14.1 '@polkadot/types-codec': 8.14.1 '@polkadot/types-create': 8.14.1 - '@polkadot/util': 10.1.6 - '@polkadot/util-crypto': 10.1.2 - rxjs: 7.5.6 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 dev: false - /@polkadot/types/9.3.3: - resolution: {integrity: sha512-By7VC9erdsJCDR9DNtgSuWSrKeLpJ7tnStS8Ii31LW1ueYDWCx1CO28fogq4UYf53pMbhNCWDGPFk1ZZn8ZchA==} + /@polkadot/types/9.4.3: + resolution: {integrity: sha512-SXHih0+TajRAZAl+uuFPpy/TxySX8oYvYg67FwRclqNsHc1Qwj5JFs0HJtuf60UkvPGqbQpNek5ND6O1VBHHQA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/keyring': 10.1.7 - '@polkadot/types-augment': 9.3.3 - '@polkadot/types-codec': 9.3.3 - '@polkadot/types-create': 9.3.3 - '@polkadot/util': 10.1.7 - '@polkadot/util-crypto': 10.1.7 - rxjs: 7.5.6 + '@babel/runtime': 7.19.0 + '@polkadot/keyring': 10.1.10 + '@polkadot/types-augment': 9.4.3 + '@polkadot/types-codec': 9.4.3 + '@polkadot/types-create': 9.4.3 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 dev: false - /@polkadot/util-crypto/10.1.2: - resolution: {integrity: sha512-lSgxSLF/XkksL8St3kyw8SCLic0JvyIf8uOezQZYyjSJKT3Gl8gGu9wCAKNAmboU0FgO8cnLO9AcAEkhCHvnyw==} + /@polkadot/util-crypto/10.1.10: + resolution: {integrity: sha512-w9h/wf4wZXeUkRnihhnfqlaKuoQtrjkjK3C5liCQkr9vx5zOsmg/nMSDP8UUFJX0msPPYpFeNvzn7oDIs6qSZA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@noble/hashes': 1.1.2 - '@noble/secp256k1': 1.6.3 - '@polkadot/networks': 10.1.2 - '@polkadot/util': 10.1.2 - '@polkadot/wasm-crypto': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm - '@polkadot/x-bigint': 10.1.2 - '@polkadot/x-randomvalues': 10.1.2 + '@babel/runtime': 7.19.0 + '@noble/hashes': 1.1.3 + '@noble/secp256k1': 1.7.0 + '@polkadot/networks': 10.1.10 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-crypto': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/x-bigint': 10.1.10 + '@polkadot/x-randomvalues': 10.1.10 '@scure/base': 1.1.1 ed2curve: 0.3.0 tweetnacl: 1.0.3 dev: false - /@polkadot/util-crypto/10.1.7: - resolution: {integrity: sha512-zGmSU7a0wdWfpDtfc+Q7fUuW+extu9o1Uh4JpkuwwZ/dxmyW5xlfqVsIScM1pdPyjJsyamX8KwsKiVsW4slasg==} + /@polkadot/util-crypto/10.1.2: + resolution: {integrity: sha512-lSgxSLF/XkksL8St3kyw8SCLic0JvyIf8uOezQZYyjSJKT3Gl8gGu9wCAKNAmboU0FgO8cnLO9AcAEkhCHvnyw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@noble/hashes': 1.1.2 '@noble/secp256k1': 1.6.3 - '@polkadot/networks': 10.1.7 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-crypto': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/x-bigint': 10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@polkadot/networks': 10.1.2 + '@polkadot/util': 10.1.2 + '@polkadot/wasm-crypto': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm + '@polkadot/x-bigint': 10.1.2 + '@polkadot/x-randomvalues': 10.1.2 '@scure/base': 1.1.1 ed2curve: 0.3.0 tweetnacl: 1.0.3 @@ -2478,7 +2495,7 @@ packages: resolution: {integrity: sha512-fWA1Nz17FxWJslweZS4l0Uo30WXb5mYV1KEACVzM+BSZAvG5eoiOAYX6VYZjyw6/7u53XKrWQlD83iPsg3KvZw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 6.11.1 '@polkadot/util': 6.11.1 '@polkadot/wasm-crypto': 4.6.1_7agzzbeuhezrwkh2zmxh2lt2xi @@ -2500,7 +2517,7 @@ packages: resolution: {integrity: sha512-nNwqUwP44eCH9jKKcPie+IHLKkg9LMe6H7hXo91hy3AtoslnNrT51tP3uAm5yllhLvswJfnAgnlHq7ybCgqeFw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/networks': 7.9.2 '@polkadot/util': 7.9.2 '@polkadot/wasm-crypto': 4.6.1_dqtjokeiluc5zkdxxwbtwmatza @@ -2522,7 +2539,7 @@ packages: resolution: {integrity: sha512-TaSuJ2aNrB5sYK7YXszkEv24nYJKRFqjF2OrggoMg6uYxUAECvTkldFnhtgeizMweRMxJIBu6bMHlSIutbWgjw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@noble/hashes': 1.0.0 '@noble/secp256k1': 1.5.5 '@polkadot/networks': 8.7.1 @@ -2539,7 +2556,7 @@ packages: resolution: {integrity: sha512-tfz6mJtPwoNteivKCmR+QklC4mr1/hGZRsDJLWKaFhanDinYZ3V2pJM1EbCI6WONLuuzlTxsDXjAffWzzRqlPA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@noble/hashes': 1.1.2 '@noble/secp256k1': 1.6.0 '@polkadot/networks': 9.7.2 @@ -2565,6 +2582,19 @@ packages: bn.js: 5.2.1 dev: false + /@polkadot/util/10.1.10: + resolution: {integrity: sha512-BQoTfSxZ3BWAgWDjgKBVdyw1AJGaoOeAidCA+LZcHV6wlMu5643AZPUnoMrW413MbbpxsIhJXtNttqOwjo8MjA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-bigint': 10.1.10 + '@polkadot/x-global': 10.1.10 + '@polkadot/x-textdecoder': 10.1.10 + '@polkadot/x-textencoder': 10.1.10 + '@types/bn.js': 5.1.1 + bn.js: 5.2.1 + dev: false + /@polkadot/util/10.1.2: resolution: {integrity: sha512-gYSpJyrrw5gZWgTVu6PJ1PBUzi3GqwmaK6XRgi4deHmQRn9TEXTToGtHmleJWnaTCRW8Vvh5B5RNNV2C/+va4w==} engines: {node: '>=14.0.0'} @@ -2582,7 +2612,7 @@ packages: resolution: {integrity: sha512-k+gCKmgwxp0smmLIR7SfiEYEToayWXjrC7pQ0PqAGxpBNOdVMSCzLMnOHf9AI5cjs/lx6ULr1fHn721wLVonkw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-bigint': 10.1.6 '@polkadot/x-global': 10.1.6 '@polkadot/x-textdecoder': 10.1.6 @@ -2591,24 +2621,11 @@ packages: bn.js: 5.2.1 dev: false - /@polkadot/util/10.1.7: - resolution: {integrity: sha512-s7gDLdNb4HUpoe3faXwoO6HwiUp8pi66voYKiUYRh1kEtW1o9vGBgyZPHPGC/FBgILzTJKii/9XxnSex60zBTA==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-bigint': 10.1.7 - '@polkadot/x-global': 10.1.7 - '@polkadot/x-textdecoder': 10.1.7 - '@polkadot/x-textencoder': 10.1.7 - '@types/bn.js': 5.1.1 - bn.js: 5.2.1 - dev: false - /@polkadot/util/6.11.1: resolution: {integrity: sha512-TEdCetr9rsdUfJZqQgX/vxLuV4XU8KMoKBMJdx+JuQ5EWemIdQkEtMBdL8k8udNGbgSNiYFA6rPppATeIxAScg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-textdecoder': 6.11.1 '@polkadot/x-textencoder': 6.11.1 '@types/bn.js': 4.11.6 @@ -2621,7 +2638,7 @@ packages: resolution: {integrity: sha512-6ABY6ErgkCsM4C6+X+AJSY4pBGwbKlHZmUtHftaiTvbaj4XuA4nTo3GU28jw8wY0Jh2cJZJvt6/BJ5GVkm5tBA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-textdecoder': 7.9.2 '@polkadot/x-textencoder': 7.9.2 '@types/bn.js': 4.11.6 @@ -2634,12 +2651,12 @@ packages: resolution: {integrity: sha512-XjY1bTo7V6OvOCe4yn8H2vifeuBciCy0gq0k5P1tlGUQLI/Yt0hvDmxcA0FEPtqg8CL+rYRG7WXGPVNjkrNvyQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-bigint': 8.7.1 '@polkadot/x-global': 8.7.1 '@polkadot/x-textdecoder': 8.7.1 '@polkadot/x-textencoder': 8.7.1 - '@types/bn.js': 5.1.0 + '@types/bn.js': 5.1.1 bn.js: 5.2.1 ip-regex: 4.3.0 dev: false @@ -2648,12 +2665,12 @@ packages: resolution: {integrity: sha512-ivTmA+KkPCq5i3O0Gk+dTds/hwdwlYCh89aKfeaG9ni3XHUbbuBgTqHneo648HqxwAwSAyiDiwE9EdXrzAdO4Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-bigint': 9.7.2 '@polkadot/x-global': 9.7.2 '@polkadot/x-textdecoder': 9.7.2 '@polkadot/x-textencoder': 9.7.2 - '@types/bn.js': 5.1.0 + '@types/bn.js': 5.1.1 bn.js: 5.2.1 ip-regex: 4.3.0 dev: false @@ -2665,7 +2682,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/x-randomvalues': 9.7.2 dev: false @@ -2677,21 +2694,21 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 10.1.2 '@polkadot/x-randomvalues': 10.1.2 dev: false - /@polkadot/wasm-bridge/6.3.1_iavvhndpjoeut6ernjqjjplteq: + /@polkadot/wasm-bridge/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-1TYkHsb9AEFhU9uZj3biEnN2yKQNzdrwSjiTvfCYnt97pnEkKsZI6cku+YPZQv5w/x9CQa5Yua9e2DVVZSivGA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/x-randomvalues': 10.1.10 dev: false /@polkadot/wasm-crypto-asmjs/4.6.1_@polkadot+util@6.11.1: @@ -2700,7 +2717,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 dev: false @@ -2710,7 +2727,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 dev: false @@ -2720,28 +2737,28 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false - /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.2: + /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.10: resolution: {integrity: sha512-zbombRfA5v/mUWQQhgg2YwaxhRmxRIrvskw65x+lruax3b6xPBFDs7yplopiJU3r8h2pTgQvX/DUksvqz2TCRQ==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.7: + /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-zbombRfA5v/mUWQQhgg2YwaxhRmxRIrvskw65x+lruax3b6xPBFDs7yplopiJU3r8h2pTgQvX/DUksvqz2TCRQ==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 dev: false /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@9.7.2: @@ -2750,7 +2767,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 dev: false @@ -2761,7 +2778,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/wasm-bridge': 6.3.1_bqbpofxh4fwo2uvuz4bljqm3ua '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@9.7.2 @@ -2776,7 +2793,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 10.1.2 '@polkadot/wasm-bridge': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.2 @@ -2784,19 +2801,19 @@ packages: '@polkadot/x-randomvalues': 10.1.2 dev: false - /@polkadot/wasm-crypto-init/6.3.1_iavvhndpjoeut6ernjqjjplteq: + /@polkadot/wasm-crypto-init/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-9yaUBcu+snwjJLmPPGl3cyGRQ1afyFGm16qzTM0sgG/ZCfUlK4uk8KWZe+sBUKgoxb2oXY7Y4WklKgQI1YBdfw==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-bridge': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-bridge': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/x-randomvalues': 10.1.10 dev: false /@polkadot/wasm-crypto-wasm/4.6.1_@polkadot+util@6.11.1: @@ -2805,7 +2822,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 dev: false @@ -2815,7 +2832,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 dev: false @@ -2825,30 +2842,30 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 dev: false - /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.2: + /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.10: resolution: {integrity: sha512-idSlzKGVzCfeCMRHsacRvqwojSaTadFxL/Dbls4z1thvfa3U9Ku0d2qVtlwg7Hj+tYWDiuP8Kygs+6bQwfs0XA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 - '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.10 dev: false - /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.7: + /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-idSlzKGVzCfeCMRHsacRvqwojSaTadFxL/Dbls4z1thvfa3U9Ku0d2qVtlwg7Hj+tYWDiuP8Kygs+6bQwfs0XA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.2 dev: false /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@9.7.2: @@ -2857,7 +2874,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/wasm-util': 6.3.1_@polkadot+util@9.7.2 dev: false @@ -2869,7 +2886,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 6.11.1 '@polkadot/wasm-crypto-asmjs': 4.6.1_@polkadot+util@6.11.1 '@polkadot/wasm-crypto-wasm': 4.6.1_@polkadot+util@6.11.1 @@ -2883,7 +2900,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 7.9.2 '@polkadot/wasm-crypto-asmjs': 4.6.1_@polkadot+util@7.9.2 '@polkadot/wasm-crypto-wasm': 4.6.1_@polkadot+util@7.9.2 @@ -2897,7 +2914,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 8.7.1 '@polkadot/wasm-crypto-asmjs': 5.1.1_@polkadot+util@8.7.1 '@polkadot/wasm-crypto-wasm': 5.1.1_@polkadot+util@8.7.1 @@ -2911,7 +2928,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 '@polkadot/wasm-bridge': 6.3.1_bqbpofxh4fwo2uvuz4bljqm3ua '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@9.7.2 @@ -2928,7 +2945,7 @@ packages: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 10.1.2 '@polkadot/wasm-bridge': 6.3.1_h5wsx5l4wlp2h2idvasjrnjqhm '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.2 @@ -2938,41 +2955,41 @@ packages: '@polkadot/x-randomvalues': 10.1.2 dev: false - /@polkadot/wasm-crypto/6.3.1_iavvhndpjoeut6ernjqjjplteq: + /@polkadot/wasm-crypto/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-OO8h0qeVkqp4xYZaRVl4iuWOEtq282pNBHDKb6SOJuI2g59eWGcKh4EQU9Me2VP6qzojIqptrkrVt7KQXC68gA==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 - '@polkadot/wasm-bridge': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/wasm-crypto-init': 6.3.1_iavvhndpjoeut6ernjqjjplteq - '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.7 - '@polkadot/x-randomvalues': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/wasm-bridge': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/wasm-crypto-init': 6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq + '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.10 + '@polkadot/x-randomvalues': 10.1.10 dev: false - /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.2: + /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.10: resolution: {integrity: sha512-12oAv5J7Yoc9m6jixrSaQCxpOkWOyzHx3DMC8qmLjRiwdBWxqLmImOVRVnFsbaxqSbhBIHRuJphVxWE+GZETDg==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 dev: false - /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.7: + /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-12oAv5J7Yoc9m6jixrSaQCxpOkWOyzHx3DMC8qmLjRiwdBWxqLmImOVRVnFsbaxqSbhBIHRuJphVxWE+GZETDg==} engines: {node: '>=14.0.0'} peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/util': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.2 dev: false /@polkadot/wasm-util/6.3.1_@polkadot+util@9.7.2: @@ -2981,7 +2998,7 @@ packages: peerDependencies: '@polkadot/util': '*' dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/util': 9.7.2 dev: false @@ -2993,6 +3010,14 @@ packages: '@polkadot/x-global': 10.1.1 dev: false + /@polkadot/x-bigint/10.1.10: + resolution: {integrity: sha512-4Jt0BO0WTby6r9A2DgkDxf/LFaICQHvSl1VSFtBf0Z0GV2n4OxkBX5x/1bdEdGEvYT5rM7RbR3xI7EL+W1ixHA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 + dev: false + /@polkadot/x-bigint/10.1.2: resolution: {integrity: sha512-TCwv3NjQdfLb7CBYR8EA5t0CrMfYx3IF4hKjctuplL+mDNI0VzNn4qVKW62AjouI8kMbn7VyBPfoBeuYX8Ixrw==} engines: {node: '>=14.0.0'} @@ -3005,23 +3030,15 @@ packages: resolution: {integrity: sha512-yeBZQ9+u49KqDBaeSw+ytshqzyaScKrDjAxpWCfOGxJaB+5Nv1W7fqi3OJ4S/HN5DYItr0a6UC14e1hiZUtZCg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 10.1.6 dev: false - /@polkadot/x-bigint/10.1.7: - resolution: {integrity: sha512-uaClHpI6cnDumIfejUKvNTkB43JleEb0V6OIufDKJ/e1aCLE3f/Ws9ggwL8ea05lQP5k5xqOzbPdizi/UvrgKQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 - dev: false - /@polkadot/x-bigint/8.7.1: resolution: {integrity: sha512-ClkhgdB/KqcAKk3zA6Qw8wBL6Wz67pYTPkrAtImpvoPJmR+l4RARauv+MH34JXMUNlNb3aUwqN6lq2Z1zN+mJg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3029,26 +3046,26 @@ packages: resolution: {integrity: sha512-qi8/DTGypFSt5vvNOsYcEaqH72lymfyidGlsHlZ6e7nNASnEhk/NaOcINiTr1ds+fpu4dtKXWAIPZufujf2JeQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false - /@polkadot/x-fetch/10.1.2: - resolution: {integrity: sha512-Zd7npq9H/kDaehiM2iyPX1+cSfuhCvqDxuS8GLTjARIVGGURBfA+NjRM6o6jsXa3HCtv+lB67Qdw1m/PSxfIpQ==} + /@polkadot/x-fetch/10.1.10: + resolution: {integrity: sha512-LvTxAN6GaJzfgZ74WFYPZrIkMEThpX5u7O4ILiExcJt87E19cSWlYSHDa5n+OLjUpq0lBV2ueF90iUblt6aHpg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 '@types/node-fetch': 2.6.2 node-fetch: 3.2.10 dev: false - /@polkadot/x-fetch/10.1.7: - resolution: {integrity: sha512-NL+xrlqUoCLwCIAvQLwOA189gSUgeSGOFjCmZ9uMkBqf35KXeZoHWse6YaoseTSlnAal3dQOGbXnYWZ4Ck2OSA==} + /@polkadot/x-fetch/10.1.2: + resolution: {integrity: sha512-Zd7npq9H/kDaehiM2iyPX1+cSfuhCvqDxuS8GLTjARIVGGURBfA+NjRM6o6jsXa3HCtv+lB67Qdw1m/PSxfIpQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.2 '@types/node-fetch': 2.6.2 node-fetch: 3.2.10 dev: false @@ -3057,7 +3074,7 @@ packages: resolution: {integrity: sha512-qJyLLnm+4SQEZ002UDz2wWnXbnnH84rIS0mLKZ5k82H4lMYY+PQflvzv6sbu463e/lgiEao+6zvWS6DSKv1Yog==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 '@types/node-fetch': 2.6.2 node-fetch: 2.6.7 @@ -3069,7 +3086,7 @@ packages: resolution: {integrity: sha512-ygNparcalYFGbspXtdtZOHvNXZBkNgmNO+um9C0JYq74K5OY9/be93uyfJKJ8JcRJtOqBfVDsJpbiRkuJ1PRfg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 '@types/node-fetch': 2.6.2 node-fetch: 2.6.7 @@ -3084,76 +3101,76 @@ packages: '@babel/runtime': 7.18.9 dev: false - /@polkadot/x-global/10.1.2: - resolution: {integrity: sha512-//r3NVLYdYQs0So0IK8Pa0pnL5pPi0geQWE6qjTtPD0oszuN9SUDqDlFQj3I3vqQOwgybbzBGNYRRinP8B2xUg==} + /@polkadot/x-global/10.1.10: + resolution: {integrity: sha512-WFfgaZSrzPlKLdnOus2mIFGzUbSDIQK6RMCfFfM9SmF3DkoxN40z5Nkni4PztfKr22stlkhmhnX/Lp/NxpuT6Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false - /@polkadot/x-global/10.1.6: - resolution: {integrity: sha512-/nraYZg0hdSjbczhDBAsHlEqeZLs0u0xa8HJrfH2lq8+HOIYkQpJPHOqiQIvEe/VFRq7Xnbij+4uffV+otzB/w==} + /@polkadot/x-global/10.1.2: + resolution: {integrity: sha512-//r3NVLYdYQs0So0IK8Pa0pnL5pPi0geQWE6qjTtPD0oszuN9SUDqDlFQj3I3vqQOwgybbzBGNYRRinP8B2xUg==} engines: {node: '>=14.0.0'} dependencies: '@babel/runtime': 7.18.9 dev: false - /@polkadot/x-global/10.1.7: - resolution: {integrity: sha512-k2ZUZyBVgDnP/Ysxapa0mthn63j6gsN2V0kZejEQPyOfCHtQQkse3jFvAWdslpWoR8j2k8SN5O6reHc0F4f7mA==} + /@polkadot/x-global/10.1.6: + resolution: {integrity: sha512-/nraYZg0hdSjbczhDBAsHlEqeZLs0u0xa8HJrfH2lq8+HOIYkQpJPHOqiQIvEe/VFRq7Xnbij+4uffV+otzB/w==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/6.11.1: resolution: {integrity: sha512-lsBK/e4KbjfieyRmnPs7bTiGbP/6EoCZz7rqD/voNS5qsJAaXgB9LR+ilubun9gK/TDpebyxgO+J19OBiQPIRw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/7.9.2: resolution: {integrity: sha512-JX5CrGWckHf1P9xKXq4vQCAuMUbL81l2hOWX7xeP8nv4caHEpmf5T1wD1iMdQBL5PFifo6Pg0V6/oZBB+bts7A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/8.7.1: resolution: {integrity: sha512-WOgUor16IihgNVdiTVGAWksYLUAlqjmODmIK1cuWrLOZtV1VBomWcb3obkO9sh5P6iWziAvCB/i+L0vnTN9ZCA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false /@polkadot/x-global/9.7.2: resolution: {integrity: sha512-3NN5JhjosaelaFWBJSlv9mb/gDAlt7RuZ8NKlOjB+LQHd9g6ZbnYi5wwjW+i/x/3E4IVbBx66uvWgNaw7IBrkg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 dev: false - /@polkadot/x-randomvalues/10.1.2: - resolution: {integrity: sha512-KOu6iZWye9KD6qoahiqZ0alrT/5FSGL4XXLhVSg69xAqD6yG2oi2aKA6cZpDU19uZGqVneqsgpebDsrZ0nLUEg==} + /@polkadot/x-randomvalues/10.1.10: + resolution: {integrity: sha512-KM4sCI/DNLIXlmnkeJIuYvh3pPuWvnkbR1a6TUB12J1izUJ+uGV+cAFRR4/EZk3oEsG/Tgivbs56meEOo3ws5A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 dev: false - /@polkadot/x-randomvalues/10.1.7: - resolution: {integrity: sha512-3er4UYOlozLGgFYWwcbmcFslmO8m82u4cAGR4AaEag0VdV7jLO/M5lTmivT/3rtLSww6sjkEfr522GM2Q5lmFg==} + /@polkadot/x-randomvalues/10.1.2: + resolution: {integrity: sha512-KOu6iZWye9KD6qoahiqZ0alrT/5FSGL4XXLhVSg69xAqD6yG2oi2aKA6cZpDU19uZGqVneqsgpebDsrZ0nLUEg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.2 dev: false /@polkadot/x-randomvalues/6.11.1: resolution: {integrity: sha512-2MfUfGZSOkuPt7GF5OJkPDbl4yORI64SUuKM25EGrJ22o1UyoBnPOClm9eYujLMD6BfDZRM/7bQqqoLW+NuHVw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 dev: false @@ -3161,7 +3178,7 @@ packages: resolution: {integrity: sha512-svQfG31yCXf6yVyIgP0NgCzEy7oc3Lw054ZspkaqjOivxYdrXaf5w3JSSUyM/MRjI2+nk+B/EyJoMYcfSwTfsQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 7.9.2 dev: false @@ -3169,7 +3186,7 @@ packages: resolution: {integrity: sha512-njt17MlfN6yNyNEti7fL12lr5qM6A1aSGkWKVuqzc7XwSBesifJuW4km5u6r2gwhXjH2eHDv9SoQ7WXu8vrrkg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3177,7 +3194,7 @@ packages: resolution: {integrity: sha512-819slnXNpoVtqdhjI19ao7w5m+Zwx11VfwCZkFQypVv3b/1UEoKG/baJA9dVI6yMvhnBN//i8mLgNy3IXWbVVw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false @@ -3185,7 +3202,7 @@ packages: resolution: {integrity: sha512-zIciEmij7SUuXXg9g/683Irx6GogxivrQS2pgBir2DI/YZq+um52+Dqg1mqsEZt74N4KMTMnzAZAP6LJOBOMww==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 rxjs: 6.6.7 dev: false @@ -3197,6 +3214,14 @@ packages: '@polkadot/x-global': 10.1.1 dev: false + /@polkadot/x-textdecoder/10.1.10: + resolution: {integrity: sha512-cAk37faYXx8IICeaq/tdl+aiIXwo3SLrx9XNoQqhX02g+SEs3ARM7zJcohj/p8ynWAI+ezNcsKn1wh174nquHw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 + dev: false + /@polkadot/x-textdecoder/10.1.2: resolution: {integrity: sha512-liMlSSKfLGTvcUPz1fMicH2HoKLgSjzxFYsbNfXJOe9GobQfSrAOcprM0j4gNJqN5EoZhze9Sf1rMTORQwomtg==} engines: {node: '>=14.0.0'} @@ -3209,23 +3234,15 @@ packages: resolution: {integrity: sha512-T+jvyv6OvUgGfOlMDLkPKEmQnZGP1CNohdEDeRr93AmeYikIfbC20qYuAc0bEBXR7/rPXgnqiEfrpkL2W3r/Ig==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 10.1.6 dev: false - /@polkadot/x-textdecoder/10.1.7: - resolution: {integrity: sha512-iAFOHludmZFOyVL8sQFv4TDqbcqQU5gwwYv74duTA+WQBgbSITJrBahSCV/rXOjUqds9pzQO3qBFzziznNnkiQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 - dev: false - /@polkadot/x-textdecoder/6.11.1: resolution: {integrity: sha512-DI1Ym2lyDSS/UhnTT2e9WutukevFZ0WGpzj4eotuG2BTHN3e21uYtYTt24SlyRNMrWJf5+TkZItmZeqs1nwAfQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 dev: false @@ -3233,7 +3250,7 @@ packages: resolution: {integrity: sha512-wfwbSHXPhrOAl12QvlIOGNkMH/N/h8PId2ytIjvM/8zPPFB5Il6DWSFLtVapOGEpIFjEWbd5t8Td4pHBVXIEbg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 7.9.2 dev: false @@ -3241,7 +3258,7 @@ packages: resolution: {integrity: sha512-ia0Ie2zi4VdQdNVD2GE2FZzBMfX//hEL4w546RMJfZM2LqDS674LofHmcyrsv5zscLnnRyCxZC1+J2dt+6MDIA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3249,7 +3266,7 @@ packages: resolution: {integrity: sha512-hhrMNZwJBmusdpqjDRpOHZoMB4hpyJt9Gu9Bi9is7/D/vq/hpxq8z7s6NxrbRyXJf1SIk6NMK0jf5XjRLdKdbw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false @@ -3261,6 +3278,14 @@ packages: '@polkadot/x-global': 10.1.1 dev: false + /@polkadot/x-textencoder/10.1.10: + resolution: {integrity: sha512-Auaql6BL5UHtWakZUQyj4y/BrM0tm4bYG5vXCMQCA1Gg0ky+46DhgpRrAQ9F7NNgWg1A6dA2I9KuAA4BTbNx0w==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 + dev: false + /@polkadot/x-textencoder/10.1.2: resolution: {integrity: sha512-bSMvesZ43Er6+jogt9IfwWN/E8bhkl4a9nNnpyS/vTh+j6n/DfDQrvYpKDpRIn7oJA6lfs/mL9Jo5jjJTngaxg==} engines: {node: '>=14.0.0'} @@ -3273,23 +3298,15 @@ packages: resolution: {integrity: sha512-e+iHdR1P/8xAc54l3gHfqozH6ZfxPkKlVVaz3vOMnzfc8cA3Zw93mLYkGtLDqv+825LkSrWSmb/bDZb6YyEEXg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 10.1.6 dev: false - /@polkadot/x-textencoder/10.1.7: - resolution: {integrity: sha512-GzjaWZDbgzZ0IQT60xuZ7cZ0wnlNVYMqpfI9KvBc58X9dPI3TIMwzbXDVzZzpjY1SAqJGs4hJse9HMWZazfhew==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 - dev: false - /@polkadot/x-textencoder/6.11.1: resolution: {integrity: sha512-8ipjWdEuqFo+R4Nxsc3/WW9CSEiprX4XU91a37ZyRVC4e9R1bmvClrpXmRQLVcAQyhRvG8DKOOtWbz8xM+oXKg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 dev: false @@ -3297,7 +3314,7 @@ packages: resolution: {integrity: sha512-A19wwYINuZwU2dUyQ/mMzB0ISjyfc4cISfL4zCMUAVgj7xVoXMYV2GfjNdMpA8Wsjch3su6pxLbtJ2wU03sRTQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 7.9.2 dev: false @@ -3305,7 +3322,7 @@ packages: resolution: {integrity: sha512-XDO0A27Xy+eJCKSxENroB8Dcnl+UclGG4ZBei+P/BqZ9rsjskUyd2Vsl6peMXAcsxwOE7g0uTvujoGM8jpKOXw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 dev: false @@ -3313,28 +3330,28 @@ packages: resolution: {integrity: sha512-GHbSdbMPixDAOnJ9cvL/x9sPNeHegPoDSqCAzY5H6/zHc/fNn0vUu0To9VpPgPhp/Jb9dbc0h8YqEyvOcOlphw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 9.7.2 dev: false - /@polkadot/x-ws/10.1.2: - resolution: {integrity: sha512-RQkc6TPM7xOKHMrE3R/8+FdE9fMGJEN7yfK/GixpMGzw98NcVedxJ1xTL19r76hJvOSeZAEks5oqgMxF8K9Pbg==} + /@polkadot/x-ws/10.1.10: + resolution: {integrity: sha512-JxDgfm0ox2XPAtdTeJXYl6qq7LY/KOPi69wRpFMczWaYUsZubO6EiRzgzjuFlHY4/oxfjS/D+YbzcjefTxHz6g==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.2 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.10 '@types/websocket': 1.0.5 websocket: 1.0.34 transitivePeerDependencies: - supports-color dev: false - /@polkadot/x-ws/10.1.7: - resolution: {integrity: sha512-aNkotxHx3qPVjiItD9lbNONs4GNzqeeZ98wHtCjd9JWl/g+xNkOVF3xQ8++1qSHPBEYSwKh9URjQH2+CD2XlvQ==} + /@polkadot/x-ws/10.1.2: + resolution: {integrity: sha512-RQkc6TPM7xOKHMrE3R/8+FdE9fMGJEN7yfK/GixpMGzw98NcVedxJ1xTL19r76hJvOSeZAEks5oqgMxF8K9Pbg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 - '@polkadot/x-global': 10.1.7 + '@babel/runtime': 7.19.0 + '@polkadot/x-global': 10.1.2 '@types/websocket': 1.0.5 websocket: 1.0.34 transitivePeerDependencies: @@ -3345,7 +3362,7 @@ packages: resolution: {integrity: sha512-GNu4ywrMlVi0QF6QSpKwYWMK6JRK+kadgN/zEhMoH1z5h8LwpqDLv128j5WspWbQti2teCQtridjf7t2Lzoe8Q==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 6.11.1 '@types/websocket': 1.0.5 websocket: 1.0.34 @@ -3357,7 +3374,7 @@ packages: resolution: {integrity: sha512-Mt0tcNzGXyKnN3DQ06alkv+JLtTfXWu6zSypFrrKHSQe3u79xMQ1nSicmpT3gWLhIa8YF+8CYJXMrqaXgCnDhw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.18.9 + '@babel/runtime': 7.19.0 '@polkadot/x-global': 8.7.1 '@types/websocket': 1.0.5 websocket: 1.0.34 @@ -3460,7 +3477,7 @@ packages: /@subsocial/definitions/0.6.11: resolution: {integrity: sha512-FQDzZmSaHXQ9x5HoudPcDYf3BmH2CN7zPbPZS+01LZXhelDN7qbNk36+pBeXki0zmtUnevWjy6LKld8zZ3XLBw==} dependencies: - '@polkadot/api': 9.3.3 + '@polkadot/api': 9.4.3 lodash.camelcase: 4.3.0 transitivePeerDependencies: - bufferutil @@ -3482,11 +3499,11 @@ packages: - supports-color dev: false - /@substrate/connect/0.7.11: - resolution: {integrity: sha512-/xiOlkmJfl2XPYQTmyWKEh2AXryEAPSMAxZXs6D/aqYDy0TKZDAp1dfQiHyPt1vMwOlnM4WJv9lPks3ZMwCP+w==} + /@substrate/connect/0.7.14: + resolution: {integrity: sha512-uW5uBmihpivshmmmw+rsg7qOV0KqVSep4rWOXFMP8aFQinvmqw4JqxP21og4H/7JZxttYUBFQVsdtXHGKJ0aVQ==} dependencies: '@substrate/connect-extension-protocol': 1.0.1 - '@substrate/smoldot-light': 0.6.30 + '@substrate/smoldot-light': 0.6.34 eventemitter3: 4.0.7 transitivePeerDependencies: - bufferutil @@ -3511,8 +3528,8 @@ packages: - supports-color dev: false - /@substrate/smoldot-light/0.6.30: - resolution: {integrity: sha512-U/F75XzxuNG+KGSujxsMAm8zUBpBON+l0oX19EnSWjvqD+smYjvcj1SeqQhFYxJjtoCQyZLedKBsZGyNbG3FbQ==} + /@substrate/smoldot-light/0.6.34: + resolution: {integrity: sha512-+HK9MaJ0HelJmpf4YYR+salJ7dhVBltmhGlyz5l8OXS9DW18fe0Z2wxEo8P5kX9CUxlCXEb8J9JBRQAYBPHbwQ==} dependencies: pako: 2.0.4 ws: 8.8.1 @@ -3535,8 +3552,8 @@ packages: resolution: {integrity: sha512-LmCH4QJRdHaeLsLTPSgJaXguMoIW+Ig9fA9LRPpeya9HefVAJ7gZuUYinldv+QmX7evNm5CL0rspNUS8l1DvXg==} dev: false - /@substrate/ss58-registry/1.28.0: - resolution: {integrity: sha512-XPSwSq4CThLyg+OnZ5/LHh3SPDQjRdGS3Ux5ClgWhRCQamlU86FCT1LBwQ/i+ximbdBfqKRRzVhm1ql3AJ9FKQ==} + /@substrate/ss58-registry/1.31.0: + resolution: {integrity: sha512-OSOmdjaq9foXfHBy9aLVMwGheygvsiZlv4dggnLOYOuhSmNCsSB/PaW4DBz+/tSdK1Fo9+ZiFW6cF24RA+m0sw==} dev: false /@substrate/txwrapper-core/3.1.7: @@ -8039,6 +8056,12 @@ packages: dependencies: tslib: 2.4.0 + /rxjs/7.5.7: + resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} + dependencies: + tslib: 2.4.0 + dev: false + /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} diff --git a/src/blocks/blocks.service.spec.ts b/src/blocks/blocks.service.spec.ts index 4133200..cec3101 100644 --- a/src/blocks/blocks.service.spec.ts +++ b/src/blocks/blocks.service.spec.ts @@ -83,6 +83,7 @@ describe('BlocksService', () => { parentHash: mockBlock.parentHash, number, } as any) || {}, + mockBlock.timestamp, ), ).resolves.toBe(mockBlock) expect(repo.create).toBeCalledTimes(1) @@ -90,6 +91,7 @@ describe('BlocksService', () => { hash: mockBlock.hash, parentHash: mockBlock.parentHash, number: mockBlock.number, + timestamp: mockBlock.timestamp, }) // TODO: fix repo.save called // expect(repo.save).toBeCalledTimes(1) @@ -109,6 +111,7 @@ describe('BlocksService', () => { parentHash: mockBlock.parentHash, number, } as any) || {}, + mockBlock.timestamp, ), ).resolves.toBe(mockBlock) expect(repo.create).toBeCalledTimes(1) @@ -116,6 +119,7 @@ describe('BlocksService', () => { hash: mockBlock.hash, parentHash: mockBlock.parentHash, number: mockBlock.number, + timestamp: mockBlock.timestamp, }) expect(repo.save).toBeCalledTimes(0) }) diff --git a/src/blocks/blocks.service.ts b/src/blocks/blocks.service.ts index 2101832..378be40 100644 --- a/src/blocks/blocks.service.ts +++ b/src/blocks/blocks.service.ts @@ -29,13 +29,14 @@ export class BlocksService { return this.blockRepository.find(args) } - async createFromHeader(header: Header): Promise { + async createFromHeader(header: Header, timestamp: number): Promise { try { const { hash, parentHash, number } = header const block = this.blockRepository.create({ hash: hash.toString().toLowerCase(), parentHash: parentHash.toString().toLowerCase(), number: parseInt(number.toHex()), + timestamp, }) const persistedBlock = await retry( async () => { diff --git a/src/blocks/entity/block.entity.ts b/src/blocks/entity/block.entity.ts index 10c0356..75f0d88 100644 --- a/src/blocks/entity/block.entity.ts +++ b/src/blocks/entity/block.entity.ts @@ -1,4 +1,4 @@ -import { Field, Int, ObjectType } from '@nestjs/graphql' +import { Field, Float, Int, ObjectType } from '@nestjs/graphql' import { BaseEntity, Column, CreateDateColumn, Entity, Index, OneToMany, PrimaryColumn } from 'typeorm' import { Transaction } from '../../transactions/entity/transaction.entity' @@ -20,6 +20,10 @@ export class Block extends BaseEntity { @Field(/* istanbul ignore next */ () => Int) number!: number + @Column('bigint') + @Field(/* istanbul ignore next */ () => Float) + timestamp!: number + @OneToMany( /* istanbul ignore next */ () => Transaction, /* istanbul ignore next */ (transaction: Transaction) => transaction.block, diff --git a/src/events/entity/event.entity.ts b/src/events/entity/event.entity.ts index 584736b..f3dd3da 100644 --- a/src/events/entity/event.entity.ts +++ b/src/events/entity/event.entity.ts @@ -1,4 +1,4 @@ -import { Field, ObjectType } from '@nestjs/graphql' +import { Field, Float, ObjectType } from '@nestjs/graphql' import { Codec } from '@polkadot/types-codec/types' import { IEventData } from '@polkadot/types/types' import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, CreateDateColumn } from 'typeorm' @@ -39,6 +39,10 @@ export class Event extends BaseEntity { @Field(/* istanbul ignore next */ () => String) topics!: string + @Column('bigint') + @Field(/* istanbul ignore next */ () => Float) + timestamp!: number + @ManyToOne( /* istanbul ignore next */ () => Transaction, /* istanbul ignore next */ (transaction: Transaction) => transaction.events, diff --git a/src/events/events.service.spec.ts b/src/events/events.service.spec.ts index 020062d..9fa1869 100644 --- a/src/events/events.service.spec.ts +++ b/src/events/events.service.spec.ts @@ -77,15 +77,13 @@ describe('EventsService', () => { }) describe('decodeEvents', () => { - it.skip('should return decoded event', () => { + it('should return decoded event', () => { jest.spyOn(contractRepo, 'findOneBy').mockResolvedValueOnce(mockContract as any) - expect(service.decodeEvents(mockEvents as any, mockContract.address)).resolves.toHaveLength(2) }) it('should return not found error', () => { jest.spyOn(contractRepo, 'findOneBy').mockResolvedValueOnce(null as any) - expect(service.decodeEvents(mockEvents as any, mockContract.address)).rejects.toThrow(Error) }) @@ -116,7 +114,12 @@ describe('EventsService', () => { .mockResolvedValueOnce(mockEvents[0] as never) .mockResolvedValueOnce(mockEvents[1] as never) - const events = await service.createEventsFromRecords(mockRecords as any, 1, mockTransaction.hash) + const events = await service.createEventsFromRecords( + mockRecords as any, + 1, + mockTransaction.hash, + mockTransaction.timestamp, + ) expect(events).toStrictEqual(mockEvents) }) @@ -133,7 +136,12 @@ describe('EventsService', () => { .mockResolvedValueOnce(mockEvents[0] as never) .mockResolvedValueOnce(mockEvents[1] as never) - const events = await service.createEventsFromRecords(mockRecords as any, 1, mockTransaction.hash) + const events = await service.createEventsFromRecords( + mockRecords as any, + 1, + mockTransaction.hash, + mockTransaction.timestamp, + ) expect(events).toStrictEqual(mockEvents) }) diff --git a/src/events/events.service.ts b/src/events/events.service.ts index bfc6ae5..c49833f 100644 --- a/src/events/events.service.ts +++ b/src/events/events.service.ts @@ -33,6 +33,7 @@ export class EventsService { records: Vec, extrinsicIndex: number, transactionHash: string, + timestamp: number, ): Promise { const events = records.filter(({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(extrinsicIndex)) const contractEmittedEvents = events.filter((record) => record?.event?.method === 'ContractEmitted') @@ -66,6 +67,7 @@ export class EventsService { topics: topics.toString(), data, transactionHash: transactionHash.toString().toLowerCase(), + timestamp, }) }) return Promise.all(eventsToSave.map((event) => this.eventRepository.save(event))) diff --git a/src/schema.graphql b/src/schema.graphql index fab45c3..dac54e0 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -6,6 +6,7 @@ type Block { hash: String! number: Int! parentHash: String! + timestamp: Float! transactions: [Transaction!]! } @@ -21,6 +22,7 @@ type Event { index: String! method: String! section: String! + timestamp: Float! topics: String! transactionHash: String } @@ -57,6 +59,7 @@ type Transaction { """Address of the signer""" signer: String + timestamp: Float! """Extra gas paid for the Tx as tip""" tip: Int diff --git a/src/subscriptions/subscriptions.service.spec.ts b/src/subscriptions/subscriptions.service.spec.ts index 4df6153..4d13370 100644 --- a/src/subscriptions/subscriptions.service.spec.ts +++ b/src/subscriptions/subscriptions.service.spec.ts @@ -4,7 +4,7 @@ import { apiMock } from '../../mocks/api-mock' import { mockBlock, mockBlocks } from '../../mocks/blocks-mocks' import { mockEvents } from '../../mocks/events-mocks' import { mockPinoService } from '../../mocks/pino-mocks' -import { mockExtrinsics, mockTransactions } from '../../mocks/transactions-mock' +import { mockExtrinsics, mockTimestamp, mockTransactions } from '../../mocks/transactions-mock' import { BlocksService } from '../blocks/blocks.service' import { EventsService } from '../events/events.service' import { TransactionsService } from '../transactions/transactions.service' @@ -58,14 +58,17 @@ describe('subscriptionsService', () => { }) describe('onModuleInit', () => { - it('should show an error message', async () => { + it('should show an error message', () => { try { - jest.spyOn(service, 'syncBlocks').mockResolvedValue(Promise.reject('grcp error')) + jest.spyOn(service, 'syncBlocks').mockImplementation(() => { + throw new Error('grcp error') + }) - await service.onModuleInit() + service.onModuleInit() fail("Shouldn't reach this point") } catch (error) { - expect(error).toBe('grcp error') + console.log(error) + expect((error as Error).message).toBe('grcp error') } }) }) @@ -130,6 +133,7 @@ describe('subscriptionsService', () => { }, extrinsics: mockExtrinsics, records: [], + timestamp: mockTimestamp, }), ) }) diff --git a/src/subscriptions/subscriptions.service.ts b/src/subscriptions/subscriptions.service.ts index af30cb6..76ca707 100644 --- a/src/subscriptions/subscriptions.service.ts +++ b/src/subscriptions/subscriptions.service.ts @@ -26,10 +26,10 @@ export class SubscriptionsService implements OnModuleInit { private readonly eventsService: EventsService, ) {} - async onModuleInit(): Promise { + onModuleInit(): void { try { this.logger.info('Subscribing to new heads...') - await this.syncBlocks() + this.syncBlocks() } catch (error) { this.logger.error({ error }, 'Error while processing blocks.') throw error @@ -84,7 +84,9 @@ export class SubscriptionsService implements OnModuleInit { async getBlockData(api: ApiPromise, hash: BlockHash) { const [block, records] = await Promise.all([api.rpc.chain.getBlock(hash), api.query.system.events.at(hash)]) const { header, extrinsics } = block.block || {} - return { header, extrinsics, records } + const timestampArgs = extrinsics.map((e) => e.method).find((m) => m.section === 'timestamp' && m.method === 'set') + const timestamp = Number(timestampArgs?.args[0].toString()) + return { header, extrinsics, records, timestamp } } getBlocksToLoad(from: number, to: number): number[] { @@ -116,11 +118,15 @@ export class SubscriptionsService implements OnModuleInit { } async registerBlockData(blockData: any) { - const { header, extrinsics, records } = blockData - const block = await this.blocksService.createFromHeader(header) - const transactions = await this.transactionsService.createTransactionsFromExtrinsics(extrinsics, block.hash) + const { header, extrinsics, records, timestamp } = blockData + const block = await this.blocksService.createFromHeader(header, timestamp) + const transactions = await this.transactionsService.createTransactionsFromExtrinsics( + extrinsics, + block.hash, + timestamp, + ) for (const [index, tx] of transactions.entries()) { - await this.eventsService.createEventsFromRecords(records, index, tx.hash) + await this.eventsService.createEventsFromRecords(records, index, tx.hash, timestamp) } return block } diff --git a/src/transactions/entity/transaction.entity.ts b/src/transactions/entity/transaction.entity.ts index f75e0be..dab2537 100644 --- a/src/transactions/entity/transaction.entity.ts +++ b/src/transactions/entity/transaction.entity.ts @@ -1,4 +1,4 @@ -import { Field, Int, ObjectType } from '@nestjs/graphql' +import { Field, Float, Int, ObjectType } from '@nestjs/graphql' import { BaseEntity, Column, @@ -35,6 +35,10 @@ export class Transaction extends BaseEntity { @Field(/* istanbul ignore next */ () => String) section!: string + @Column('bigint') + @Field(/* istanbul ignore next */ () => Float) + timestamp!: number + @ManyToOne(/* istanbul ignore next */ () => Block, /* istanbul ignore next */ (block: Block) => block.transactions, { onDelete: 'SET NULL', nullable: true, diff --git a/src/transactions/transactions.service.spec.ts b/src/transactions/transactions.service.spec.ts index a7394d2..b208ebe 100644 --- a/src/transactions/transactions.service.spec.ts +++ b/src/transactions/transactions.service.spec.ts @@ -3,7 +3,13 @@ import { Test, TestingModule } from '@nestjs/testing' import { getRepositoryToken } from '@nestjs/typeorm' import { Repository } from 'typeorm' import { mockPinoService } from '../../mocks/pino-mocks' -import { mockExtrinsics, mockSavedTransactions, mockTransaction, mockTransactions } from '../../mocks/transactions-mock' +import { + mockExtrinsics, + mockSavedTransactions, + mockTimestamp, + mockTransaction, + mockTransactions, +} from '../../mocks/transactions-mock' import { Transaction } from './entity/transaction.entity' import { TransactionsService } from './transactions.service' @@ -66,7 +72,7 @@ describe('TransactionsService', () => { .mockResolvedValueOnce(mockSavedTransactions[0]) .mockResolvedValueOnce(mockSavedTransactions[1]) const blockHash = '0xffcfae3ecc9ab7b79fc0cd451dad35477a32219b219b29584b968826ac04c1a1' - const savedTxs = await service.createTransactionsFromExtrinsics(mockExtrinsics as any, blockHash) + const savedTxs = await service.createTransactionsFromExtrinsics(mockExtrinsics as any, blockHash, mockTimestamp) mockSavedTransactions.forEach((tx, i) => { expect(savedTxs[i].hash).toEqual(tx.hash) expect(savedTxs[i].blockHash).toEqual(tx.blockHash) @@ -87,7 +93,7 @@ describe('TransactionsService', () => { .mockResolvedValueOnce(mockSavedTransactions[0]) .mockResolvedValueOnce(mockSavedTransactions[1]) const blockHash = '0xffcfae3ecc9ab7b79fc0cd451dad35477a32219b219b29584b968826ac04c1a1' - const savedTxs = await service.createTransactionsFromExtrinsics(mockExtrinsics as any, blockHash) + const savedTxs = await service.createTransactionsFromExtrinsics(mockExtrinsics as any, blockHash, mockTimestamp) mockSavedTransactions.forEach((tx, i) => { expect(savedTxs[i].hash).toEqual(tx.hash) expect(savedTxs[i].blockHash).toEqual(tx.blockHash) @@ -107,7 +113,7 @@ describe('TransactionsService', () => { try { jest.spyOn(repo, 'findOneBy').mockResolvedValue(Promise.reject("Can't connect to database")) const blockHash = '0xffcfae3ecc9ab7b79fc0cd451dad35477a32219b219b29584b968826ac04c1a1' - await service.createTransactionsFromExtrinsics(mockExtrinsics as any, blockHash) + await service.createTransactionsFromExtrinsics(mockExtrinsics as any, blockHash, mockTimestamp) fail("Shouldn't reach this point") } catch (error) { expect(error).toEqual("Can't connect to database") diff --git a/src/transactions/transactions.service.ts b/src/transactions/transactions.service.ts index 4672115..6452b00 100644 --- a/src/transactions/transactions.service.ts +++ b/src/transactions/transactions.service.ts @@ -35,6 +35,7 @@ export class TransactionsService { async createTransactionsFromExtrinsics( extrinsics: Vec>, blockHash: string, + timestamp: number, ): Promise { return Promise.all( extrinsics.map(async (extrinsic) => { @@ -50,6 +51,7 @@ export class TransactionsService { signer: signer.toString(), tip: tip.toNumber(), blockHash: blockHash.toLowerCase(), + timestamp, }) const transaction = await retry( async () => { From 1360272f4d9761d4274a3ebccbf27657ad072334 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 10 Oct 2022 16:02:48 -0300 Subject: [PATCH 03/28] lint --- docker-compose.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 770c9b0..db2bc8a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -20,12 +20,12 @@ services: - .:/usr/src/app - /usr/src/app/node_modules - /usr/src/app/dist + env_file: + - .env networks: ink-explorer-network: aliases: - "backend" - env_file: - - .env postgres: image: postgres:14.4 restart: always From 1d2353226568c1fbbd285d09de0e2fc94422019c Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 10 Oct 2022 16:05:09 -0300 Subject: [PATCH 04/28] dockerfile --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index db2bc8a..e8597d3 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -13,7 +13,7 @@ services: - postgres build: context: . - dockerfile: dev.Dockerfile + dockerfile: Dockerfile #dev.Dockefile ports: - 8080:8080 volumes: From 0596e1c375288d86c390fbe0c06be6be4c9ee6de Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Tue, 11 Oct 2022 17:48:36 -0300 Subject: [PATCH 05/28] query blocks with order --- src/blocks/blocks.service.ts | 6 +++++- src/blocks/dtos/fetch-blocks.input.ts | 6 ++++++ src/schema.graphql | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/blocks/blocks.service.ts b/src/blocks/blocks.service.ts index 378be40..c40e44f 100644 --- a/src/blocks/blocks.service.ts +++ b/src/blocks/blocks.service.ts @@ -26,7 +26,11 @@ export class BlocksService { } async fetchBlocks(args: FetchBlocksInput): Promise { - return this.blockRepository.find(args) + const { skip, take, orderByNumber, orderAsc } = args + const order: any = {} + const by = orderByNumber ? 'number' : 'timestamp' + order[by] = orderAsc ? 'ASC' : 'DESC' + return this.blockRepository.find({ skip, take, order }) } async createFromHeader(header: Header, timestamp: number): Promise { diff --git a/src/blocks/dtos/fetch-blocks.input.ts b/src/blocks/dtos/fetch-blocks.input.ts index 19639e1..b9e73b1 100644 --- a/src/blocks/dtos/fetch-blocks.input.ts +++ b/src/blocks/dtos/fetch-blocks.input.ts @@ -7,4 +7,10 @@ export class FetchBlocksInput { @Field(/* istanbul ignore next */ () => Int) take = 10 + + @Field(/* istanbul ignore next */ () => Boolean) + orderByNumber?: boolean = false + + @Field(/* istanbul ignore next */ () => Boolean) + orderAsc?: boolean = false } diff --git a/src/schema.graphql b/src/schema.graphql index dac54e0..49c73ca 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -34,7 +34,7 @@ type Mutation { type Query { decodeEvents(contractAddress: String!): String! getBlock(hash: String!): Block! - getBlocks(skip: Int = 0, take: Int = 10): [Block!]! + getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! getEvents(contract: String, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! From fda3102ab7616975a8336b0bc2d92b55324285c3 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Wed, 12 Oct 2022 18:04:01 -0300 Subject: [PATCH 06/28] adding transaction data --- pnpm-lock.yaml | 197 +++++++++++++++++- src/schema.graphql | 19 +- src/transactions/entity/transaction.entity.ts | 54 ++++- src/transactions/transactions.service.ts | 43 +++- 4 files changed, 285 insertions(+), 28 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d5b8e1..be8b5ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1651,6 +1651,23 @@ packages: - utf-8-validate dev: false + /@polkadot/api-augment/9.5.1: + resolution: {integrity: sha512-9NQ2miIKVJvyhR2Zhk0XcHA+pgnWhQ0815lqcq0kz9ny5JHUFeGlNtxECw7AEnxoiC81EqpfWkOHpJpfiIcOmw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/api-base': 9.5.1 + '@polkadot/rpc-augment': 9.5.1 + '@polkadot/types': 9.5.1 + '@polkadot/types-augment': 9.5.1 + '@polkadot/types-codec': 9.5.1 + '@polkadot/util': 10.1.10 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@polkadot/api-base/7.15.1: resolution: {integrity: sha512-UlhLdljJPDwGpm5FxOjvJNFTxXMRFaMuVNx6EklbuetbBEJ/Amihhtj0EJRodxQwtZ4ZtPKYKt+g+Dn7OJJh4g==} engines: {node: '>=14.0.0'} @@ -1693,6 +1710,21 @@ packages: - utf-8-validate dev: false + /@polkadot/api-base/9.5.1: + resolution: {integrity: sha512-3qsMsIhYbU3zp+YnP5h6Hg98y3B+FrxgPW7r2Uk6Kp1uSPmIzhMCyGuxur/BAcDVbd3KME+zWLHJDYOdyhuUwQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/rpc-core': 9.5.1 + '@polkadot/types': 9.5.1 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@polkadot/api-contract/9.4.3: resolution: {integrity: sha512-PnBZyUgaLf7DGHkfrRrYISGRXLpZXykJj3L6KKcMrZL7MgiPvyhYzNVXCTmhGOjPQxhaYUDk8VPWmArLf8qT2Q==} engines: {node: '>=14.0.0'} @@ -1784,6 +1816,26 @@ packages: - utf-8-validate dev: false + /@polkadot/api-derive/9.5.1: + resolution: {integrity: sha512-fKlKQe8WZ3jrm44w/zptMofljW5qj+jZxnryK08CAH/MINlZArPfCtn+EJla2ND9aTnRMUWlEBtytyCPImI/Hg==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/api': 9.5.1 + '@polkadot/api-augment': 9.5.1 + '@polkadot/api-base': 9.5.1 + '@polkadot/rpc-core': 9.5.1 + '@polkadot/types': 9.5.1 + '@polkadot/types-codec': 9.5.1 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@polkadot/api/4.17.1: resolution: {integrity: sha512-uuNIKWC+PjM+1AARRu4NLWOEudZE6DW8UOlaubx3uGhPywqPIP+HGWP2I6PqRGYKARBWxxOvca1Q7WoKzpYC8w==} engines: {node: '>=14.0.0'} @@ -1883,6 +1935,33 @@ packages: - utf-8-validate dev: false + /@polkadot/api/9.5.1: + resolution: {integrity: sha512-A2i/+mCl6cbFJ84ExMcWosUDfq0gVvzyKftkbRMs0oDzvHVVucTm0nCCzBgi/ltvSsFq8oJQ4pVqNTfT/IXgeQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/api-augment': 9.5.1 + '@polkadot/api-base': 9.5.1 + '@polkadot/api-derive': 9.5.1 + '@polkadot/keyring': 10.1.10 + '@polkadot/rpc-augment': 9.5.1 + '@polkadot/rpc-core': 9.5.1 + '@polkadot/rpc-provider': 9.5.1 + '@polkadot/types': 9.5.1 + '@polkadot/types-augment': 9.5.1 + '@polkadot/types-codec': 9.5.1 + '@polkadot/types-create': 9.5.1 + '@polkadot/types-known': 9.5.1 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + eventemitter3: 4.0.7 + rxjs: 7.5.7 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@polkadot/apps-config/0.118.1: resolution: {integrity: sha512-m1pIkWADyWEd/3WXZezjXwjCGr6in1Cd1FGiQciC5oHJbma3bJIMpJrQfhGeprxhTbJ/fDKdEWw0YEaUhgu54A==} dependencies: @@ -2087,6 +2166,21 @@ packages: - utf-8-validate dev: false + /@polkadot/rpc-augment/9.5.1: + resolution: {integrity: sha512-7Qm6oIoVIqv6VOaIqDal45hUTb3TVZ58S3zkSr60p/dPMlGCaFMcojtfcQErHtCW0hgvzFNsDl9ShpXRcPWu7g==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/rpc-core': 9.5.1 + '@polkadot/types': 9.5.1 + '@polkadot/types-codec': 9.5.1 + '@polkadot/util': 10.1.10 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@polkadot/rpc-core/4.17.1: resolution: {integrity: sha512-1gqYaYuSSQsRmt3ol55jmjBP/euKyAh4PwSj94I2wu0fngK/FZwVZNDJZn/Ib68X/s38TBIgqJ6+YdUdr3z1xw==} engines: {node: '>=14.0.0'} @@ -2147,6 +2241,22 @@ packages: - utf-8-validate dev: false + /@polkadot/rpc-core/9.5.1: + resolution: {integrity: sha512-8CXgBVTEUjeuN5VOwS6MjTeqpN+9qrNJAAwNEba36/72g6Wgg3flza11kx0luQ6OLPVgCM7OcAjZ17p16phXDA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/rpc-augment': 9.5.1 + '@polkadot/rpc-provider': 9.5.1 + '@polkadot/types': 9.5.1 + '@polkadot/util': 10.1.10 + rxjs: 7.5.7 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@polkadot/rpc-provider/4.17.1: resolution: {integrity: sha512-vlU1H5mnfP0Ej8PbjcxwF9ZlT7LtcpekOKI4iYfMnfdelSUKUVyaD5PC8yRGIg9fxkorA6OM5AZs116jAl3TLA==} engines: {node: '>=14.0.0'} @@ -2230,6 +2340,29 @@ packages: - utf-8-validate dev: false + /@polkadot/rpc-provider/9.5.1: + resolution: {integrity: sha512-CxyEo1SzwbcByUsrW5RUm5GTLNK7yjmVlTMseex8zQLO4+4erqUoQzr6TTIPSt4LWyk+TjbZdtGtlt7p6i2nJg==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/keyring': 10.1.10 + '@polkadot/types': 9.5.1 + '@polkadot/types-support': 9.5.1 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + '@polkadot/x-fetch': 10.1.10 + '@polkadot/x-global': 10.1.10 + '@polkadot/x-ws': 10.1.10 + '@substrate/connect': 0.7.14 + eventemitter3: 4.0.7 + mock-socket: 9.1.5 + nock: 13.2.9 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /@polkadot/types-augment/7.15.1: resolution: {integrity: sha512-aqm7xT/66TCna0I2utpIekoquKo0K5pnkA/7WDzZ6gyD8he2h0IXfe8xWjVmuyhjxrT/C/7X1aUF2Z0xlOCwzQ==} engines: {node: '>=14.0.0'} @@ -2260,6 +2393,16 @@ packages: '@polkadot/util': 10.1.10 dev: false + /@polkadot/types-augment/9.5.1: + resolution: {integrity: sha512-1AzQpGe5bGttYbbjR1UhV19htsFjgqJ651eyT3YdRqo1hotZ2GwTCkGXuTJtcmQQH9G09xUUwS3nx8WsSyQ70A==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/types': 9.5.1 + '@polkadot/types-codec': 9.5.1 + '@polkadot/util': 10.1.10 + dev: false + /@polkadot/types-codec/7.15.1: resolution: {integrity: sha512-nI11dT7FGaeDd/fKPD8iJRFGhosOJoyjhZ0gLFFDlKCaD3AcGBRTTY8HFJpP/5QXXhZzfZsD93fVKrosnegU0Q==} engines: {node: '>=14.0.0'} @@ -2286,6 +2429,15 @@ packages: '@polkadot/x-bigint': 10.1.10 dev: false + /@polkadot/types-codec/9.5.1: + resolution: {integrity: sha512-7Dy8TeApu4lN8DqdMZLuh34ocdHQh9jzAob6cQl1fl1ypOiCO/SwPjFkj0Xnhh7QQz9X9w63jZzbaFR3PPT+0g==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + '@polkadot/x-bigint': 10.1.10 + dev: false + /@polkadot/types-create/7.15.1: resolution: {integrity: sha512-+HiaHn7XOwP0kv/rVdORlVkNuMoxuvt+jd67A/CeEreJiXqRLu+S61Mdk7wi6719PTaOal1hTDFfyGrtUd8FSQ==} engines: {node: '>=14.0.0'} @@ -2313,6 +2465,15 @@ packages: '@polkadot/util': 10.1.10 dev: false + /@polkadot/types-create/9.5.1: + resolution: {integrity: sha512-pUQ1U0mho5aKRdi4iR9DP9ldIoj9U+ApHIeYyxkBY8RexMQOpkt8PZfpFhg4z2H5vZj/sgNIBXq65HjXuyu+9w==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/types-codec': 9.5.1 + '@polkadot/util': 10.1.10 + dev: false + /@polkadot/types-known/4.17.1: resolution: {integrity: sha512-YkOwGrO+k9aVrBR8FgYHnfJKhOfpdgC5ZRYNL/xJ9oa7lBYqPts9ENAxeBmJS/5IGeDF9f32MNyrCP2umeCXWg==} engines: {node: '>=14.0.0'} @@ -2369,6 +2530,18 @@ packages: '@polkadot/util': 10.1.10 dev: false + /@polkadot/types-known/9.5.1: + resolution: {integrity: sha512-SedfPDxJREYPATa7X2Fv26z6UVPYv6v9Z9P4nulnC6Yl8C2+Q4A/VIqTtgsJc0DU1YT3gM8ofVxircfHqqRVNA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/networks': 10.1.10 + '@polkadot/types': 9.5.1 + '@polkadot/types-codec': 9.5.1 + '@polkadot/types-create': 9.5.1 + '@polkadot/util': 10.1.10 + dev: false + /@polkadot/types-support/7.15.1: resolution: {integrity: sha512-FIK251ffVo+NaUXLlaJeB5OvT7idDd3uxaoBM6IwsS87rzt2CcWMyCbu0uX89AHZUhSviVx7xaBxfkGEqMePWA==} engines: {node: '>=14.0.0'} @@ -2393,6 +2566,14 @@ packages: '@polkadot/util': 10.1.10 dev: false + /@polkadot/types-support/9.5.1: + resolution: {integrity: sha512-mjenEGNT/ReY1xFexb37NDgV7QHHBBfWt31ZQMZKDkQL+R2P0rXFpmitcE3eOCV3oY4mf+GaU2N/ZfnsFl3tPQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.10 + dev: false + /@polkadot/types/4.17.1: resolution: {integrity: sha512-rjW4OFdwvFekzN3ATLibC2JPSd8AWt5YepJhmuCPdwH26r3zB8bEC6dM7YQExLVUmygVPvgXk5ffHI6RAdXBMg==} engines: {node: '>=14.0.0'} @@ -2457,6 +2638,20 @@ packages: rxjs: 7.5.7 dev: false + /@polkadot/types/9.5.1: + resolution: {integrity: sha512-xuhYq+O4JRl2iqLVEwKVHnfOA9AfwoNlHzrFx2DChDcIWdmgmUDASq9TkZhBP+jx81SieMH7iTf4zY6UwPKYQw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/keyring': 10.1.10 + '@polkadot/types-augment': 9.5.1 + '@polkadot/types-codec': 9.5.1 + '@polkadot/types-create': 9.5.1 + '@polkadot/util': 10.1.10 + '@polkadot/util-crypto': 10.1.10 + rxjs: 7.5.7 + dev: false + /@polkadot/util-crypto/10.1.10: resolution: {integrity: sha512-w9h/wf4wZXeUkRnihhnfqlaKuoQtrjkjK3C5liCQkr9vx5zOsmg/nMSDP8UUFJX0msPPYpFeNvzn7oDIs6qSZA==} engines: {node: '>=14.0.0'} @@ -3477,7 +3672,7 @@ packages: /@subsocial/definitions/0.6.11: resolution: {integrity: sha512-FQDzZmSaHXQ9x5HoudPcDYf3BmH2CN7zPbPZS+01LZXhelDN7qbNk36+pBeXki0zmtUnevWjy6LKld8zZ3XLBw==} dependencies: - '@polkadot/api': 9.4.3 + '@polkadot/api': 9.5.1 lodash.camelcase: 4.3.0 transitivePeerDependencies: - bufferutil diff --git a/src/schema.graphql b/src/schema.graphql index 49c73ca..4e96301 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -43,24 +43,23 @@ type Query { } type Transaction { + args: String blockHash: String + callIndex: String + decimals: String + encodedLength: Int + era: String events: [Event!]! - - """Transaction hash""" hash: String! method: String! - - """Transaction's nonce""" nonce: Int section: String! - - """Signature generated by the signer""" signature: String! - - """Address of the signer""" signer: String + ss58: String timestamp: Float! - - """Extra gas paid for the Tx as tip""" tip: Int + tokens: String + type: Int + version: Int } \ No newline at end of file diff --git a/src/transactions/entity/transaction.entity.ts b/src/transactions/entity/transaction.entity.ts index dab2537..75cadbf 100644 --- a/src/transactions/entity/transaction.entity.ts +++ b/src/transactions/entity/transaction.entity.ts @@ -20,7 +20,7 @@ export class Transaction extends BaseEntity { @PrimaryColumn({ unique: true, }) - @Field(/* istanbul ignore next */ () => String, { description: 'Transaction hash' }) + @Field(/* istanbul ignore next */ () => String) hash!: string @Column() @@ -29,11 +29,11 @@ export class Transaction extends BaseEntity { @Column() @Field(/* istanbul ignore next */ () => String) - method!: string + section!: string @Column() @Field(/* istanbul ignore next */ () => String) - section!: string + method!: string @Column('bigint') @Field(/* istanbul ignore next */ () => Float) @@ -52,27 +52,59 @@ export class Transaction extends BaseEntity { events!: Event[] @Column() - @Field(/* istanbul ignore next */ () => String, { description: 'Signature generated by the signer' }) + @Field(/* istanbul ignore next */ () => String) signature?: string @Column() - @Field(/* istanbul ignore next */ () => String, { description: 'Address of the signer', nullable: true }) + @Field(/* istanbul ignore next */ () => String, { nullable: true }) signer?: string @Column('int') - @Field(/* istanbul ignore next */ () => Int, { description: "Transaction's nonce", nullable: true }) + @Field(/* istanbul ignore next */ () => Int, { nullable: true }) nonce?: number @Column('int') - @Field(/* istanbul ignore next */ () => Int, { description: 'Extra gas paid for the Tx as tip', nullable: true }) + @Field(/* istanbul ignore next */ () => Int, { nullable: true }) tip?: number + @Column('int') + @Field(/* istanbul ignore next */ () => Int, { nullable: true }) + version?: number + + @Column('int') + @Field(/* istanbul ignore next */ () => Int, { nullable: true }) + type?: number + + @Column('int') + @Field(/* istanbul ignore next */ () => Int, { nullable: true }) + encodedLength?: number + + @Column() + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + callIndex?: string + + @Column() + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + decimals?: string + + @Column() + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + ss58?: string + + @Column() + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + tokens?: string + + @Column() + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + era?: string + + @Column() + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + args?: string + @CreateDateColumn({ default: /* istanbul ignore next */ () => 'NOW()', }) createdDate!: Date - // TODO: add this - //era?: GenericExtrinsicEra - // We are not storing this for now - //args: any } diff --git a/src/transactions/transactions.service.ts b/src/transactions/transactions.service.ts index 6452b00..3732ab7 100644 --- a/src/transactions/transactions.service.ts +++ b/src/transactions/transactions.service.ts @@ -3,7 +3,7 @@ import { Injectable, NotFoundException } from '@nestjs/common' import { InjectRepository } from '@nestjs/typeorm' import { GenericExtrinsic } from '@polkadot/types' import { Vec } from '@polkadot/types-codec' -import { AnyTuple } from '@polkadot/types-codec/types' +import { AnyTuple, ArgsDef } from '@polkadot/types-codec/types' import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import { Repository } from 'typeorm' import { FetchTransactionsInput } from './dtos/fetch-transactions.input' @@ -40,18 +40,40 @@ export class TransactionsService { return Promise.all( extrinsics.map(async (extrinsic) => { try { - const { hash: transactionHash, nonce, signature, signer, tip } = extrinsic - const { method, section } = extrinsic.method + const { + hash: transactionHash, + nonce, + signature, + signer, + encodedLength, + registry, + tip, + era, + version, + type, + callIndex, + } = extrinsic + const { method, section, args, argsDef } = extrinsic.method + const formattedArgs = this.formatArgs(args, argsDef) const tx = this.transactionRepository.create({ hash: transactionHash.toString().toLowerCase(), - method: method, + blockHash: blockHash.toLowerCase(), section: section, - nonce: nonce.toNumber(), + method: method, signature: signature.toString(), signer: signer.toString(), + nonce: nonce.toNumber(), tip: tip.toNumber(), - blockHash: blockHash.toLowerCase(), timestamp, + version: version, + type: type, + encodedLength: encodedLength, + callIndex: callIndex.toString(), + decimals: registry.chainDecimals.toString(), + ss58: registry.chainSS58?.toString(), + tokens: registry.chainTokens.toString(), + era: JSON.stringify(era), + args: JSON.stringify(formattedArgs), }) const transaction = await retry( async () => { @@ -73,4 +95,13 @@ export class TransactionsService { }), ) } + + // This function creates a new object with the same keys as the argsDef object and the values from the args object + formatArgs(args: AnyTuple, argsDef: ArgsDef) { + const formattedArgs: any = {} + Object.keys(argsDef).forEach((key: any, index) => { + formattedArgs[key] = args[index] + }) + return formattedArgs + } } From e901c9f1b43795fc399180100255174b3a5f0bfa Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 17 Oct 2022 18:34:01 -0400 Subject: [PATCH 07/28] adding block data and transactions queries --- src/blocks/blocks.service.ts | 3 ++- src/blocks/entity/block.entity.ts | 4 ++++ src/schema.graphql | 2 ++ src/subscriptions/subscriptions.service.ts | 8 ++++---- .../dtos/fetch-transactions-by-contract.input.ts | 16 ++++++++++++++++ src/transactions/transactions.resolver.ts | 6 ++++++ src/transactions/transactions.service.ts | 15 ++++++++++++++- 7 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 src/transactions/dtos/fetch-transactions-by-contract.input.ts diff --git a/src/blocks/blocks.service.ts b/src/blocks/blocks.service.ts index c40e44f..1377c3f 100644 --- a/src/blocks/blocks.service.ts +++ b/src/blocks/blocks.service.ts @@ -33,7 +33,7 @@ export class BlocksService { return this.blockRepository.find({ skip, take, order }) } - async createFromHeader(header: Header, timestamp: number): Promise { + async createFromHeader(header: Header, timestamp: number, encodedLength: number): Promise { try { const { hash, parentHash, number } = header const block = this.blockRepository.create({ @@ -41,6 +41,7 @@ export class BlocksService { parentHash: parentHash.toString().toLowerCase(), number: parseInt(number.toHex()), timestamp, + encodedLength, }) const persistedBlock = await retry( async () => { diff --git a/src/blocks/entity/block.entity.ts b/src/blocks/entity/block.entity.ts index 75f0d88..d741691 100644 --- a/src/blocks/entity/block.entity.ts +++ b/src/blocks/entity/block.entity.ts @@ -24,6 +24,10 @@ export class Block extends BaseEntity { @Field(/* istanbul ignore next */ () => Float) timestamp!: number + @Column('bigint') + @Field(/* istanbul ignore next */ () => Float) + encodedLength!: number + @OneToMany( /* istanbul ignore next */ () => Transaction, /* istanbul ignore next */ (transaction: Transaction) => transaction.block, diff --git a/src/schema.graphql b/src/schema.graphql index 4e96301..d963194 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -3,6 +3,7 @@ # ------------------------------------------------------ type Block { + encodedLength: Float! hash: String! number: Int! parentHash: String! @@ -39,6 +40,7 @@ type Query { getEvents(contract: String, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! getTransactions(blockHash: String, skip: Int = 0, take: Int = 20): [Transaction!]! + getTransactionsByAddress(address: String!, order: String = "DESC", skip: Int = 0, take: Int = 10): [Transaction!]! status: String! } diff --git a/src/subscriptions/subscriptions.service.ts b/src/subscriptions/subscriptions.service.ts index 76ca707..49cc848 100644 --- a/src/subscriptions/subscriptions.service.ts +++ b/src/subscriptions/subscriptions.service.ts @@ -43,7 +43,6 @@ export class SubscriptionsService implements OnModuleInit { async syncBlocks() { const api = await SubscriptionsService.connect() - const lastDBBlockNumber = (await this.blocksService.getLastBlock())?.number || 0 const lastBlockNumber = (await api.rpc.chain.getHeader()).number.toNumber() const loadFromBlockNumber = LOAD_ALL_BLOCKS ? FIRST_BLOCK_TO_LOAD : lastDBBlockNumber @@ -83,10 +82,11 @@ export class SubscriptionsService implements OnModuleInit { async getBlockData(api: ApiPromise, hash: BlockHash) { const [block, records] = await Promise.all([api.rpc.chain.getBlock(hash), api.query.system.events.at(hash)]) + const encodedLength = block.encodedLength const { header, extrinsics } = block.block || {} const timestampArgs = extrinsics.map((e) => e.method).find((m) => m.section === 'timestamp' && m.method === 'set') const timestamp = Number(timestampArgs?.args[0].toString()) - return { header, extrinsics, records, timestamp } + return { header, extrinsics, records, timestamp, encodedLength } } getBlocksToLoad(from: number, to: number): number[] { @@ -118,8 +118,8 @@ export class SubscriptionsService implements OnModuleInit { } async registerBlockData(blockData: any) { - const { header, extrinsics, records, timestamp } = blockData - const block = await this.blocksService.createFromHeader(header, timestamp) + const { header, extrinsics, records, timestamp, encodedLength } = blockData + const block = await this.blocksService.createFromHeader(header, timestamp, encodedLength) const transactions = await this.transactionsService.createTransactionsFromExtrinsics( extrinsics, block.hash, diff --git a/src/transactions/dtos/fetch-transactions-by-contract.input.ts b/src/transactions/dtos/fetch-transactions-by-contract.input.ts new file mode 100644 index 0000000..efa06f2 --- /dev/null +++ b/src/transactions/dtos/fetch-transactions-by-contract.input.ts @@ -0,0 +1,16 @@ +import { Field, Int, ArgsType } from '@nestjs/graphql' + +@ArgsType() +export class FetchTransactionsByContractInput { + @Field(/* istanbul ignore next */ () => String) + address: string | undefined + + @Field(/* istanbul ignore next */ () => Int) + skip? = 0 + + @Field(/* istanbul ignore next */ () => Int) + take? = 10 + + @Field(/* istanbul ignore next */ () => String) + order?: 'ASC' | 'DESC' = 'DESC' +} diff --git a/src/transactions/transactions.resolver.ts b/src/transactions/transactions.resolver.ts index bcf08b4..59b6402 100644 --- a/src/transactions/transactions.resolver.ts +++ b/src/transactions/transactions.resolver.ts @@ -2,6 +2,7 @@ import { Args, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql' import { FetchEventsInput } from '../events/dtos/fetch-events.input' import { Event } from '../events/entity/event.entity' import { EventsService } from '../events/events.service' +import { FetchTransactionsByContractInput } from './dtos/fetch-transactions-by-contract.input' import { FetchTransactionsInput } from './dtos/fetch-transactions.input' import { Transaction } from './entity/transaction.entity' import { TransactionsService } from './transactions.service' @@ -19,6 +20,11 @@ export class TransactionsResolver { return this.transactionsService.fetchTransactions(args) } + @Query(/* istanbul ignore next */ () => [Transaction]) + async getTransactionsByAddress(@Args() args: FetchTransactionsByContractInput) { + return this.transactionsService.getTransactionsByContractAddress(args) + } + @ResolveField('events', /* istanbul ignore next */ () => [Event]) async getEvents(@Parent() transaction: Transaction) { const { hash } = transaction diff --git a/src/transactions/transactions.service.ts b/src/transactions/transactions.service.ts index 3732ab7..43a06c6 100644 --- a/src/transactions/transactions.service.ts +++ b/src/transactions/transactions.service.ts @@ -6,6 +6,7 @@ import { Vec } from '@polkadot/types-codec' import { AnyTuple, ArgsDef } from '@polkadot/types-codec/types' import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import { Repository } from 'typeorm' +import { FetchTransactionsByContractInput } from './dtos/fetch-transactions-by-contract.input' import { FetchTransactionsInput } from './dtos/fetch-transactions.input' import { Transaction } from './entity/transaction.entity' const retry = require('async-await-retry') @@ -29,7 +30,7 @@ export class TransactionsService { async fetchTransactions(args: FetchTransactionsInput): Promise { const { skip, take, blockHash } = args - return this.transactionRepository.find({ skip, take, where: { blockHash } }) + return this.transactionRepository.find({ skip, take, where: { blockHash }, order: { timestamp: 'DESC' } }) } async createTransactionsFromExtrinsics( @@ -104,4 +105,16 @@ export class TransactionsService { }) return formattedArgs } + + async getTransactionsByContractAddress(args: FetchTransactionsByContractInput): Promise { + const { skip = 0, take = 10, address, order = 'DESC' } = args + return this.transactionRepository + .createQueryBuilder('transaction') + .leftJoin('transaction.events', 'event') + .where('event.contractAddress = :address', { address }) + .skip(skip) + .take(take) + .orderBy('transaction.timestamp', order) + .getMany() + } } From 9c0f5495f6578f6f1b16ba42be094e310701bb39 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 17 Oct 2022 18:38:58 -0400 Subject: [PATCH 08/28] rename resolver function --- src/schema.graphql | 2 +- src/transactions/transactions.resolver.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schema.graphql b/src/schema.graphql index d963194..389387d 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -40,7 +40,7 @@ type Query { getEvents(contract: String, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! getTransactions(blockHash: String, skip: Int = 0, take: Int = 20): [Transaction!]! - getTransactionsByAddress(address: String!, order: String = "DESC", skip: Int = 0, take: Int = 10): [Transaction!]! + getTransactionsByContract(address: String!, order: String = "DESC", skip: Int = 0, take: Int = 10): [Transaction!]! status: String! } diff --git a/src/transactions/transactions.resolver.ts b/src/transactions/transactions.resolver.ts index 59b6402..3f5d9ff 100644 --- a/src/transactions/transactions.resolver.ts +++ b/src/transactions/transactions.resolver.ts @@ -21,7 +21,7 @@ export class TransactionsResolver { } @Query(/* istanbul ignore next */ () => [Transaction]) - async getTransactionsByAddress(@Args() args: FetchTransactionsByContractInput) { + async getTransactionsByContract(@Args() args: FetchTransactionsByContractInput) { return this.transactionsService.getTransactionsByContractAddress(args) } From 401262c5a125f40d834e384a228f15fcf04ffb5b Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 17 Oct 2022 18:54:27 -0400 Subject: [PATCH 09/28] rename resolver function --- src/transactions/dtos/fetch-transactions-by-contract.input.ts | 4 ++-- src/transactions/transactions.service.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/transactions/dtos/fetch-transactions-by-contract.input.ts b/src/transactions/dtos/fetch-transactions-by-contract.input.ts index efa06f2..ef83c7b 100644 --- a/src/transactions/dtos/fetch-transactions-by-contract.input.ts +++ b/src/transactions/dtos/fetch-transactions-by-contract.input.ts @@ -11,6 +11,6 @@ export class FetchTransactionsByContractInput { @Field(/* istanbul ignore next */ () => Int) take? = 10 - @Field(/* istanbul ignore next */ () => String) - order?: 'ASC' | 'DESC' = 'DESC' + @Field(/* istanbul ignore next */ () => Boolean) + orderAsc?: boolean = false } diff --git a/src/transactions/transactions.service.ts b/src/transactions/transactions.service.ts index 43a06c6..cf1b7e6 100644 --- a/src/transactions/transactions.service.ts +++ b/src/transactions/transactions.service.ts @@ -107,14 +107,14 @@ export class TransactionsService { } async getTransactionsByContractAddress(args: FetchTransactionsByContractInput): Promise { - const { skip = 0, take = 10, address, order = 'DESC' } = args + const { skip = 0, take = 10, address, orderAsc = false } = args return this.transactionRepository .createQueryBuilder('transaction') .leftJoin('transaction.events', 'event') .where('event.contractAddress = :address', { address }) .skip(skip) .take(take) - .orderBy('transaction.timestamp', order) + .orderBy('transaction.timestamp', orderAsc ? 'ASC' : 'DESC') .getMany() } } From 70d791a38f6174009c2e85060796cc2376b51abb Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 17 Oct 2022 19:13:34 -0400 Subject: [PATCH 10/28] schema --- src/schema.graphql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schema.graphql b/src/schema.graphql index 389387d..689e4d7 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -40,7 +40,7 @@ type Query { getEvents(contract: String, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! getTransactions(blockHash: String, skip: Int = 0, take: Int = 20): [Transaction!]! - getTransactionsByContract(address: String!, order: String = "DESC", skip: Int = 0, take: Int = 10): [Transaction!]! + getTransactionsByContract(address: String!, orderAsc: Boolean = false, skip: Int = 0, take: Int = 10): [Transaction!]! status: String! } From 27a17c7db3489d8790eda007c5eaddccbdf72263 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 17 Oct 2022 22:40:51 -0400 Subject: [PATCH 11/28] events order asc --- src/events/dtos/fetch-events.input.ts | 3 +++ src/events/events.service.ts | 9 +++++++-- src/schema.graphql | 4 ++-- src/transactions/dtos/fetch-transactions.input.ts | 3 +++ src/transactions/transactions.service.ts | 9 +++++++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/events/dtos/fetch-events.input.ts b/src/events/dtos/fetch-events.input.ts index 009115a..839a4d0 100644 --- a/src/events/dtos/fetch-events.input.ts +++ b/src/events/dtos/fetch-events.input.ts @@ -8,6 +8,9 @@ export class FetchEventsInput { @Field(/* istanbul ignore next */ () => Int, { nullable: true }) take? = 20 + @Field(/* istanbul ignore next */ () => Boolean) + orderAsc?: boolean = false + @Field(/* istanbul ignore next */ () => String, { nullable: true }) contract?: string diff --git a/src/events/events.service.ts b/src/events/events.service.ts index c49833f..991c6e9 100644 --- a/src/events/events.service.ts +++ b/src/events/events.service.ts @@ -21,8 +21,13 @@ export class EventsService { ) {} async fetchEvents(args: FetchEventsInput): Promise { - const { skip, take, contract, transactionHash } = args - return this.eventRepository.find({ skip, take, where: { contract: { address: contract }, transactionHash } }) + const { skip, take, contract, transactionHash, orderAsc } = args + return this.eventRepository.find({ + skip, + take, + where: { contract: { address: contract }, transactionHash }, + order: { timestamp: orderAsc ? 'ASC' : 'DESC' }, + }) } async findById(id: string): Promise { diff --git a/src/schema.graphql b/src/schema.graphql index 689e4d7..e7f8536 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -37,9 +37,9 @@ type Query { getBlock(hash: String!): Block! getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! - getEvents(contract: String, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! + getEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! - getTransactions(blockHash: String, skip: Int = 0, take: Int = 20): [Transaction!]! + getTransactions(blockHash: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20): [Transaction!]! getTransactionsByContract(address: String!, orderAsc: Boolean = false, skip: Int = 0, take: Int = 10): [Transaction!]! status: String! } diff --git a/src/transactions/dtos/fetch-transactions.input.ts b/src/transactions/dtos/fetch-transactions.input.ts index 8312501..f4b9e0b 100644 --- a/src/transactions/dtos/fetch-transactions.input.ts +++ b/src/transactions/dtos/fetch-transactions.input.ts @@ -10,4 +10,7 @@ export class FetchTransactionsInput { @Field(/* istanbul ignore next */ () => String, { nullable: true }) blockHash?: string + + @Field(/* istanbul ignore next */ () => Boolean) + orderAsc?: boolean = false } diff --git a/src/transactions/transactions.service.ts b/src/transactions/transactions.service.ts index cf1b7e6..a7c8787 100644 --- a/src/transactions/transactions.service.ts +++ b/src/transactions/transactions.service.ts @@ -29,8 +29,13 @@ export class TransactionsService { } async fetchTransactions(args: FetchTransactionsInput): Promise { - const { skip, take, blockHash } = args - return this.transactionRepository.find({ skip, take, where: { blockHash }, order: { timestamp: 'DESC' } }) + const { skip, take, blockHash, orderAsc } = args + return this.transactionRepository.find({ + skip, + take, + where: { blockHash }, + order: { timestamp: orderAsc ? 'ASC' : 'DESC' }, + }) } async createTransactionsFromExtrinsics( From 71cca52ccbc29582b107326071a2078a458273ea Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Tue, 18 Oct 2022 12:06:46 -0400 Subject: [PATCH 12/28] get event resolver --- src/events/events.resolver.ts | 5 +++++ src/schema.graphql | 1 + 2 files changed, 6 insertions(+) diff --git a/src/events/events.resolver.ts b/src/events/events.resolver.ts index 252d599..4e50703 100644 --- a/src/events/events.resolver.ts +++ b/src/events/events.resolver.ts @@ -11,6 +11,11 @@ export class EventsResolver { return this.eventsService.fetchEvents(args) } + @Query(/* istanbul ignore next */ () => Event) + async getEvent(@Args('id', { type: () => String }) id: string) { + return this.eventsService.findById(id) + } + @Query(/* istanbul ignore next */ () => String) async decodeEvents(@Args('contractAddress', { type: () => String }) contractAddress: string) { try { diff --git a/src/schema.graphql b/src/schema.graphql index e7f8536..1a75d7e 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -37,6 +37,7 @@ type Query { getBlock(hash: String!): Block! getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! + getEvent(id: String!): Event! getEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! getTransactions(blockHash: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20): [Transaction!]! From 90b957cc19c20a6c5a54a18913fa541b63860d64 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Wed, 19 Oct 2022 13:32:20 -0400 Subject: [PATCH 13/28] decode resolvers --- src/events/entity/event.entity.ts | 5 +++ src/events/events.resolver.ts | 41 ++++++++++++++++++++-- src/events/events.service.ts | 17 ++++++++- src/schema.graphql | 5 ++- src/subscriptions/subscriptions.service.ts | 2 +- 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/events/entity/event.entity.ts b/src/events/entity/event.entity.ts index f3dd3da..46bf318 100644 --- a/src/events/entity/event.entity.ts +++ b/src/events/entity/event.entity.ts @@ -1,4 +1,5 @@ import { Field, Float, ObjectType } from '@nestjs/graphql' +import { DecodedEvent } from '@polkadot/api-contract/types' import { Codec } from '@polkadot/types-codec/types' import { IEventData } from '@polkadot/types/types' import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, CreateDateColumn } from 'typeorm' @@ -58,6 +59,10 @@ export class Event extends BaseEntity { @Field(/* istanbul ignore next */ () => String, { nullable: true }) data?: Codec[] & IEventData + @Column({ type: 'jsonb', nullable: true, default: {} }) + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + decodedData?: DecodedEvent + @CreateDateColumn({ default: /* istanbul ignore next */ () => 'NOW()', }) diff --git a/src/events/events.resolver.ts b/src/events/events.resolver.ts index 4e50703..f1efbae 100644 --- a/src/events/events.resolver.ts +++ b/src/events/events.resolver.ts @@ -17,10 +17,27 @@ export class EventsResolver { } @Query(/* istanbul ignore next */ () => String) - async decodeEvents(@Args('contractAddress', { type: () => String }) contractAddress: string) { + async decodeEvents(@Args() args: FetchEventsInput) { try { - const events = await this.eventsService.fetchEvents({ contract: contractAddress as string }) - const response = await this.eventsService.decodeEvents(events, contractAddress as string) + const events = await this.eventsService.fetchEvents(args) + const decodedEvents = await this.eventsService.decodeEvents(events, args.contract as string) + return JSON.stringify(decodedEvents) + } catch (error) { + return error + } + } + + @Query(/* istanbul ignore next */ () => String) + async decodeEvent( + @Args('contractAddress', { type: () => String }) contractAddress: string, + @Args('id', { type: () => String }) id: string, + ) { + try { + const event = await this.eventsService.findById(id) + if (!event) { + throw new Error('Event not found') + } + const response = await this.eventsService.decodeEvents([event], contractAddress as string) return JSON.stringify(response) } catch (error) { @@ -33,4 +50,22 @@ export class EventsResolver { const { data } = event return JSON.stringify(data) } + + @ResolveField('decodedData', /* istanbul ignore next */ () => String) + async decodedData(@Parent() event: Event) { + const { decodedData } = event + if (!decodedData) { + return '' + } + return JSON.stringify(decodedData) + } + + @ResolveField('formattedData', /* istanbul ignore next */ () => String) + async formattedData(@Parent() event: Event) { + const { decodedData } = event + if (!decodedData) { + return '' + } + return JSON.stringify(this.eventsService.formatDecoded(decodedData)) + } } diff --git a/src/events/events.service.ts b/src/events/events.service.ts index 991c6e9..86d3da2 100644 --- a/src/events/events.service.ts +++ b/src/events/events.service.ts @@ -5,6 +5,7 @@ import { DecodedEvent } from '@polkadot/api-contract/types' import { Vec } from '@polkadot/types-codec' import { FrameSystemEventRecord } from '@polkadot/types/lookup' import { numberToU8a } from '@polkadot/util' +import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import { Repository } from 'typeorm' import { fromString } from 'uuidv4' import { Contract } from '../contracts/entity/contract.entity' @@ -14,6 +15,8 @@ import { Event } from './entity/event.entity' @Injectable() export class EventsService { constructor( + @InjectPinoLogger(EventsService.name) + private readonly logger: PinoLogger, @InjectRepository(Event) private readonly eventRepository: Repository, @InjectRepository(Contract) @@ -82,7 +85,19 @@ export class EventsService { const contract = await this.contractRespository.findOneBy({ address: contractAddress }) if (!contract) throw new Error('Contract not found') if (!contract.metadata) throw new Error('Upload the metadata first') - return events.map((event) => this.decodeContractEmittedEvent(contract.metadata as string, event.data)) + return Promise.all( + events.map(async (event) => { + try { + const decodedEvent = this.decodeContractEmittedEvent(contract.metadata as string, event.data) + event.decodedData = decodedEvent + await this.eventRepository.update(event.id, event) + return decodedEvent + } catch (error) { + this.logger.error(error) + return { message: "Can't decode event", error } + } + }), + ) } decodeContractEmittedEvent(abi: string | Record, data: any): DecodedEvent { diff --git a/src/schema.graphql b/src/schema.graphql index 1a75d7e..f8de91a 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -19,6 +19,8 @@ type Contract { type Event { data: String + decodedData: String + formattedData: String! id: String! index: String! method: String! @@ -33,7 +35,8 @@ type Mutation { } type Query { - decodeEvents(contractAddress: String!): String! + decodeEvent(contractAddress: String!, id: String!): String! + decodeEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): String! getBlock(hash: String!): Block! getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! diff --git a/src/subscriptions/subscriptions.service.ts b/src/subscriptions/subscriptions.service.ts index 49cc848..d4eb28f 100644 --- a/src/subscriptions/subscriptions.service.ts +++ b/src/subscriptions/subscriptions.service.ts @@ -85,7 +85,7 @@ export class SubscriptionsService implements OnModuleInit { const encodedLength = block.encodedLength const { header, extrinsics } = block.block || {} const timestampArgs = extrinsics.map((e) => e.method).find((m) => m.section === 'timestamp' && m.method === 'set') - const timestamp = Number(timestampArgs?.args[0].toString()) + const timestamp = Number(timestampArgs?.args[0].toString()) || Date.now() return { header, extrinsics, records, timestamp, encodedLength } } From 1e64adb8e9c9b08e66c44fd42c2a2fb57f4a0fb5 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Wed, 19 Oct 2022 16:33:06 -0400 Subject: [PATCH 14/28] version resolvers --- src/app.resolver.ts | 5 +++++ src/schema.graphql | 1 + 2 files changed, 6 insertions(+) diff --git a/src/app.resolver.ts b/src/app.resolver.ts index 57a7f9e..12041d1 100644 --- a/src/app.resolver.ts +++ b/src/app.resolver.ts @@ -6,4 +6,9 @@ export class AppResolver { status(): string { return 'running' } + + @Query(/* istanbul ignore next */ () => String) + version(): string { + return 'v1.0.1' + } } diff --git a/src/schema.graphql b/src/schema.graphql index f8de91a..cb255e6 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -46,6 +46,7 @@ type Query { getTransactions(blockHash: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20): [Transaction!]! getTransactionsByContract(address: String!, orderAsc: Boolean = false, skip: Int = 0, take: Int = 10): [Transaction!]! status: String! + version: String! } type Transaction { From c053269e3ffb20157d3dbffe7848374b4add1b7a Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Thu, 20 Oct 2022 14:42:43 -0400 Subject: [PATCH 15/28] contract queries resolver added --- pnpm-lock.yaml | 411 +++++++++++++++------ src/contracts/contracts.resolver.ts | 19 +- src/contracts/contracts.service.ts | 66 +++- src/contracts/entity/contract.entity.ts | 19 + src/schema.graphql | 9 + src/subscriptions/subscriptions.service.ts | 10 +- src/utils.ts | 5 + 7 files changed, 422 insertions(+), 117 deletions(-) create mode 100644 src/utils.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be8b5ba..7b71472 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -661,6 +661,13 @@ packages: regenerator-runtime: 0.13.9 dev: false + /@babel/runtime/7.19.4: + resolution: {integrity: sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.9 + dev: false + /@babel/template/7.18.10: resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} engines: {node: '>=6.9.0'} @@ -1651,17 +1658,17 @@ packages: - utf-8-validate dev: false - /@polkadot/api-augment/9.5.1: - resolution: {integrity: sha512-9NQ2miIKVJvyhR2Zhk0XcHA+pgnWhQ0815lqcq0kz9ny5JHUFeGlNtxECw7AEnxoiC81EqpfWkOHpJpfiIcOmw==} + /@polkadot/api-augment/9.5.2: + resolution: {integrity: sha512-dH6QMY8Z3zI6CrgSU3eSe6f0KWDb5PYGztg/FXGPrjh7Vjic7syWZ1LD6zaHJAFWDp80BEdEXfqr4lConrCKGg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/api-base': 9.5.1 - '@polkadot/rpc-augment': 9.5.1 - '@polkadot/types': 9.5.1 - '@polkadot/types-augment': 9.5.1 - '@polkadot/types-codec': 9.5.1 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/api-base': 9.5.2 + '@polkadot/rpc-augment': 9.5.2 + '@polkadot/types': 9.5.2 + '@polkadot/types-augment': 9.5.2 + '@polkadot/types-codec': 9.5.2 + '@polkadot/util': 10.1.11 transitivePeerDependencies: - bufferutil - supports-color @@ -1710,14 +1717,14 @@ packages: - utf-8-validate dev: false - /@polkadot/api-base/9.5.1: - resolution: {integrity: sha512-3qsMsIhYbU3zp+YnP5h6Hg98y3B+FrxgPW7r2Uk6Kp1uSPmIzhMCyGuxur/BAcDVbd3KME+zWLHJDYOdyhuUwQ==} + /@polkadot/api-base/9.5.2: + resolution: {integrity: sha512-BBsH9SLB1FHgjdiU32cZX1puL3Eh8IjOJHjRsO/5SdttciQhF5g/u/m/mM/55qnlXmffI9s2Jre18G0XtVU9Aw==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/rpc-core': 9.5.1 - '@polkadot/types': 9.5.1 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/rpc-core': 9.5.2 + '@polkadot/types': 9.5.2 + '@polkadot/util': 10.1.11 rxjs: 7.5.7 transitivePeerDependencies: - bufferutil @@ -1816,19 +1823,19 @@ packages: - utf-8-validate dev: false - /@polkadot/api-derive/9.5.1: - resolution: {integrity: sha512-fKlKQe8WZ3jrm44w/zptMofljW5qj+jZxnryK08CAH/MINlZArPfCtn+EJla2ND9aTnRMUWlEBtytyCPImI/Hg==} + /@polkadot/api-derive/9.5.2: + resolution: {integrity: sha512-kWn12dlqfIES1trNLd3O1i2qa4T97v/co1VMCgVstICwCt3+mGZgpxkMqQqPiWHagKEVeBNoAn+h8eOiQlbujA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/api': 9.5.1 - '@polkadot/api-augment': 9.5.1 - '@polkadot/api-base': 9.5.1 - '@polkadot/rpc-core': 9.5.1 - '@polkadot/types': 9.5.1 - '@polkadot/types-codec': 9.5.1 - '@polkadot/util': 10.1.10 - '@polkadot/util-crypto': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/api': 9.5.2 + '@polkadot/api-augment': 9.5.2 + '@polkadot/api-base': 9.5.2 + '@polkadot/rpc-core': 9.5.2 + '@polkadot/types': 9.5.2 + '@polkadot/types-codec': 9.5.2 + '@polkadot/util': 10.1.11 + '@polkadot/util-crypto': 10.1.11 rxjs: 7.5.7 transitivePeerDependencies: - bufferutil @@ -1935,25 +1942,25 @@ packages: - utf-8-validate dev: false - /@polkadot/api/9.5.1: - resolution: {integrity: sha512-A2i/+mCl6cbFJ84ExMcWosUDfq0gVvzyKftkbRMs0oDzvHVVucTm0nCCzBgi/ltvSsFq8oJQ4pVqNTfT/IXgeQ==} - engines: {node: '>=14.0.0'} - dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/api-augment': 9.5.1 - '@polkadot/api-base': 9.5.1 - '@polkadot/api-derive': 9.5.1 - '@polkadot/keyring': 10.1.10 - '@polkadot/rpc-augment': 9.5.1 - '@polkadot/rpc-core': 9.5.1 - '@polkadot/rpc-provider': 9.5.1 - '@polkadot/types': 9.5.1 - '@polkadot/types-augment': 9.5.1 - '@polkadot/types-codec': 9.5.1 - '@polkadot/types-create': 9.5.1 - '@polkadot/types-known': 9.5.1 - '@polkadot/util': 10.1.10 - '@polkadot/util-crypto': 10.1.10 + /@polkadot/api/9.5.2: + resolution: {integrity: sha512-iEF/E8vQan3fHmIEl3bX7Yn/1jQLlvSDwPOxiQdj4tIcF36HX6vCbkdhQKRif0CNYES58TA9EKFiCNg81k+kXw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/api-augment': 9.5.2 + '@polkadot/api-base': 9.5.2 + '@polkadot/api-derive': 9.5.2 + '@polkadot/keyring': 10.1.11 + '@polkadot/rpc-augment': 9.5.2 + '@polkadot/rpc-core': 9.5.2 + '@polkadot/rpc-provider': 9.5.2 + '@polkadot/types': 9.5.2 + '@polkadot/types-augment': 9.5.2 + '@polkadot/types-codec': 9.5.2 + '@polkadot/types-create': 9.5.2 + '@polkadot/types-known': 9.5.2 + '@polkadot/util': 10.1.11 + '@polkadot/util-crypto': 10.1.11 eventemitter3: 4.0.7 rxjs: 7.5.7 transitivePeerDependencies: @@ -2018,6 +2025,15 @@ packages: '@polkadot/util-crypto': 10.1.10 dev: false + /@polkadot/keyring/10.1.11: + resolution: {integrity: sha512-Nv8cZaOA/KbdslDMTklJ58+y+UPpic3+oMQoozuq48Ccjv7WeW2BX47XM/RNE8nYFg6EHa6Whfm4IFaFb8s7ag==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/util': 10.1.11 + '@polkadot/util-crypto': 10.1.11 + dev: false + /@polkadot/keyring/10.1.2: resolution: {integrity: sha512-b6hP3JFGYjsNNT3NO7I8fWRPqovgL4IvjvLttkfzpM6eM1zRRupqQ+Q50Jdl/3YUcr26PcxQcdRqJku4WyDABg==} engines: {node: '>=14.0.0'} @@ -2083,6 +2099,15 @@ packages: '@substrate/ss58-registry': 1.31.0 dev: false + /@polkadot/networks/10.1.11: + resolution: {integrity: sha512-4FfOVETXwh6PL6wd6fYJMkRSQKm+xUw3vR5rHqcAnB696FpMFPPErc6asgZ9lYMyzNJRY3yG86HQpFhtCv1nGA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/util': 10.1.11 + '@substrate/ss58-registry': 1.33.0 + dev: false + /@polkadot/networks/10.1.2: resolution: {integrity: sha512-67ZPqdhLYDGNX1jMEa3+hujh9j30Dr9AdqgdjE8Z3GdWoEVRp9Zda3DXMnDIQlRBQ32pRZty7dFhIq61Bv/whQ==} engines: {node: '>=14.0.0'} @@ -2166,15 +2191,15 @@ packages: - utf-8-validate dev: false - /@polkadot/rpc-augment/9.5.1: - resolution: {integrity: sha512-7Qm6oIoVIqv6VOaIqDal45hUTb3TVZ58S3zkSr60p/dPMlGCaFMcojtfcQErHtCW0hgvzFNsDl9ShpXRcPWu7g==} + /@polkadot/rpc-augment/9.5.2: + resolution: {integrity: sha512-QAcunC7p/T4xy6e4m0Q1c9tiVYxnm+S9o10tmtx0K4qXzrc/4I2/tsw3nEGi3BzJhvMpFondSQGcJ3gyLwpmVA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/rpc-core': 9.5.1 - '@polkadot/types': 9.5.1 - '@polkadot/types-codec': 9.5.1 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/rpc-core': 9.5.2 + '@polkadot/types': 9.5.2 + '@polkadot/types-codec': 9.5.2 + '@polkadot/util': 10.1.11 transitivePeerDependencies: - bufferutil - supports-color @@ -2241,15 +2266,15 @@ packages: - utf-8-validate dev: false - /@polkadot/rpc-core/9.5.1: - resolution: {integrity: sha512-8CXgBVTEUjeuN5VOwS6MjTeqpN+9qrNJAAwNEba36/72g6Wgg3flza11kx0luQ6OLPVgCM7OcAjZ17p16phXDA==} + /@polkadot/rpc-core/9.5.2: + resolution: {integrity: sha512-4PbNz0GEp3FXYOnsS7mDHZy9DNVBOl56fq8vs09rLkEkrrvGkHmCvabEEWL7OPbwBzwzsCxdgI+IdkVTUKXPkQ==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/rpc-augment': 9.5.1 - '@polkadot/rpc-provider': 9.5.1 - '@polkadot/types': 9.5.1 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/rpc-augment': 9.5.2 + '@polkadot/rpc-provider': 9.5.2 + '@polkadot/types': 9.5.2 + '@polkadot/util': 10.1.11 rxjs: 7.5.7 transitivePeerDependencies: - bufferutil @@ -2340,19 +2365,19 @@ packages: - utf-8-validate dev: false - /@polkadot/rpc-provider/9.5.1: - resolution: {integrity: sha512-CxyEo1SzwbcByUsrW5RUm5GTLNK7yjmVlTMseex8zQLO4+4erqUoQzr6TTIPSt4LWyk+TjbZdtGtlt7p6i2nJg==} + /@polkadot/rpc-provider/9.5.2: + resolution: {integrity: sha512-Sn2jfvAsvQcl35o0up8JR/XbDMS/3YVDEN2sFuzXtiD77W2njukItbZT+BolfAW+biAUs3bNomump5k/YLiLKg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/keyring': 10.1.10 - '@polkadot/types': 9.5.1 - '@polkadot/types-support': 9.5.1 - '@polkadot/util': 10.1.10 - '@polkadot/util-crypto': 10.1.10 - '@polkadot/x-fetch': 10.1.10 - '@polkadot/x-global': 10.1.10 - '@polkadot/x-ws': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/keyring': 10.1.11 + '@polkadot/types': 9.5.2 + '@polkadot/types-support': 9.5.2 + '@polkadot/util': 10.1.11 + '@polkadot/util-crypto': 10.1.11 + '@polkadot/x-fetch': 10.1.11 + '@polkadot/x-global': 10.1.11 + '@polkadot/x-ws': 10.1.11 '@substrate/connect': 0.7.14 eventemitter3: 4.0.7 mock-socket: 9.1.5 @@ -2393,14 +2418,14 @@ packages: '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-augment/9.5.1: - resolution: {integrity: sha512-1AzQpGe5bGttYbbjR1UhV19htsFjgqJ651eyT3YdRqo1hotZ2GwTCkGXuTJtcmQQH9G09xUUwS3nx8WsSyQ70A==} + /@polkadot/types-augment/9.5.2: + resolution: {integrity: sha512-LDJdv/84sECwA0R5lK85/orxjoozJe3+2jeLjRiKr8S6qm9XRfz0wLCSF866kpSGBZ4B1dYBUhzjoSu95y2Jug==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/types': 9.5.1 - '@polkadot/types-codec': 9.5.1 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/types': 9.5.2 + '@polkadot/types-codec': 9.5.2 + '@polkadot/util': 10.1.11 dev: false /@polkadot/types-codec/7.15.1: @@ -2429,13 +2454,13 @@ packages: '@polkadot/x-bigint': 10.1.10 dev: false - /@polkadot/types-codec/9.5.1: - resolution: {integrity: sha512-7Dy8TeApu4lN8DqdMZLuh34ocdHQh9jzAob6cQl1fl1ypOiCO/SwPjFkj0Xnhh7QQz9X9w63jZzbaFR3PPT+0g==} + /@polkadot/types-codec/9.5.2: + resolution: {integrity: sha512-FJPjE3ceTGTcadeC8d5C+aSR8SLKuQrXKIBmMNBky+WwzEo0vufRqxFWcPLxAOEeeUPgBXS967tP15+UU4psGA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/util': 10.1.10 - '@polkadot/x-bigint': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/util': 10.1.11 + '@polkadot/x-bigint': 10.1.11 dev: false /@polkadot/types-create/7.15.1: @@ -2465,13 +2490,13 @@ packages: '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-create/9.5.1: - resolution: {integrity: sha512-pUQ1U0mho5aKRdi4iR9DP9ldIoj9U+ApHIeYyxkBY8RexMQOpkt8PZfpFhg4z2H5vZj/sgNIBXq65HjXuyu+9w==} + /@polkadot/types-create/9.5.2: + resolution: {integrity: sha512-YbplL8K0LqUEHoV3FgZ5B83oVV67KGbLXsWHVVaUZBPsmtXJXrbBfSyJgl/80I2n4lXEBmg3sFAYMbaSTvL05A==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/types-codec': 9.5.1 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/types-codec': 9.5.2 + '@polkadot/util': 10.1.11 dev: false /@polkadot/types-known/4.17.1: @@ -2530,16 +2555,16 @@ packages: '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-known/9.5.1: - resolution: {integrity: sha512-SedfPDxJREYPATa7X2Fv26z6UVPYv6v9Z9P4nulnC6Yl8C2+Q4A/VIqTtgsJc0DU1YT3gM8ofVxircfHqqRVNA==} + /@polkadot/types-known/9.5.2: + resolution: {integrity: sha512-iNaGOF6dGiTvy3Ns8Z7WNjYD1SGnZiapDAKPH4brPuJqMpN6/FxYpfPSSOKx+IJEamsdINcaggb87eWyPxH8CA==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/networks': 10.1.10 - '@polkadot/types': 9.5.1 - '@polkadot/types-codec': 9.5.1 - '@polkadot/types-create': 9.5.1 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/networks': 10.1.11 + '@polkadot/types': 9.5.2 + '@polkadot/types-codec': 9.5.2 + '@polkadot/types-create': 9.5.2 + '@polkadot/util': 10.1.11 dev: false /@polkadot/types-support/7.15.1: @@ -2566,12 +2591,12 @@ packages: '@polkadot/util': 10.1.10 dev: false - /@polkadot/types-support/9.5.1: - resolution: {integrity: sha512-mjenEGNT/ReY1xFexb37NDgV7QHHBBfWt31ZQMZKDkQL+R2P0rXFpmitcE3eOCV3oY4mf+GaU2N/ZfnsFl3tPQ==} + /@polkadot/types-support/9.5.2: + resolution: {integrity: sha512-Zdbl5fvGQjUkyE1r67vhyPEqLUwlZ35GCnkoobY9MgN6gylhSjNue/shpG4uGsEjWVQL7GkFkrPiwtzDArVilg==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/util': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/util': 10.1.11 dev: false /@polkadot/types/4.17.1: @@ -2638,17 +2663,17 @@ packages: rxjs: 7.5.7 dev: false - /@polkadot/types/9.5.1: - resolution: {integrity: sha512-xuhYq+O4JRl2iqLVEwKVHnfOA9AfwoNlHzrFx2DChDcIWdmgmUDASq9TkZhBP+jx81SieMH7iTf4zY6UwPKYQw==} + /@polkadot/types/9.5.2: + resolution: {integrity: sha512-6C5xzOrMK+fu0JMOlSO+8dPDhpwKPOaKMv3v5BMvBEWtDNKM81/QQoAoYT7DSVXq/V16icSFxPs9IWC+6Qq5ag==} engines: {node: '>=14.0.0'} dependencies: - '@babel/runtime': 7.19.0 - '@polkadot/keyring': 10.1.10 - '@polkadot/types-augment': 9.5.1 - '@polkadot/types-codec': 9.5.1 - '@polkadot/types-create': 9.5.1 - '@polkadot/util': 10.1.10 - '@polkadot/util-crypto': 10.1.10 + '@babel/runtime': 7.19.4 + '@polkadot/keyring': 10.1.11 + '@polkadot/types-augment': 9.5.2 + '@polkadot/types-codec': 9.5.2 + '@polkadot/types-create': 9.5.2 + '@polkadot/util': 10.1.11 + '@polkadot/util-crypto': 10.1.11 rxjs: 7.5.7 dev: false @@ -2669,6 +2694,23 @@ packages: tweetnacl: 1.0.3 dev: false + /@polkadot/util-crypto/10.1.11: + resolution: {integrity: sha512-wG63frIMAR5T/HXGM0SFNzZZdk7qDBsfLXfn6PIZiXCCCsdEYPzS5WltB7fkhicYpbePJ7VgdCAddj1l4IcGyg==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@noble/hashes': 1.1.3 + '@noble/secp256k1': 1.7.0 + '@polkadot/networks': 10.1.11 + '@polkadot/util': 10.1.11 + '@polkadot/wasm-crypto': 6.3.1_kq5krb3p4bzvrcxi3xa2lgyh6u + '@polkadot/x-bigint': 10.1.11 + '@polkadot/x-randomvalues': 10.1.11 + '@scure/base': 1.1.1 + ed2curve: 0.3.0 + tweetnacl: 1.0.3 + dev: false + /@polkadot/util-crypto/10.1.2: resolution: {integrity: sha512-lSgxSLF/XkksL8St3kyw8SCLic0JvyIf8uOezQZYyjSJKT3Gl8gGu9wCAKNAmboU0FgO8cnLO9AcAEkhCHvnyw==} engines: {node: '>=14.0.0'} @@ -2790,6 +2832,19 @@ packages: bn.js: 5.2.1 dev: false + /@polkadot/util/10.1.11: + resolution: {integrity: sha512-6m51lw6g6ilqO/k4BQY7rD0lYM9NCnC4FiM7CEEUc7j8q86qxdcZ88zdNldkhNsTIQnfmCtkK3GRzZW6VYrbUw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/x-bigint': 10.1.11 + '@polkadot/x-global': 10.1.11 + '@polkadot/x-textdecoder': 10.1.11 + '@polkadot/x-textencoder': 10.1.11 + '@types/bn.js': 5.1.1 + bn.js: 5.2.1 + dev: false + /@polkadot/util/10.1.2: resolution: {integrity: sha512-gYSpJyrrw5gZWgTVu6PJ1PBUzi3GqwmaK6XRgi4deHmQRn9TEXTToGtHmleJWnaTCRW8Vvh5B5RNNV2C/+va4w==} engines: {node: '>=14.0.0'} @@ -2894,6 +2949,18 @@ packages: '@polkadot/x-randomvalues': 10.1.2 dev: false + /@polkadot/wasm-bridge/6.3.1_kq5krb3p4bzvrcxi3xa2lgyh6u: + resolution: {integrity: sha512-1TYkHsb9AEFhU9uZj3biEnN2yKQNzdrwSjiTvfCYnt97pnEkKsZI6cku+YPZQv5w/x9CQa5Yua9e2DVVZSivGA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@polkadot/util': '*' + '@polkadot/x-randomvalues': '*' + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.11 + '@polkadot/x-randomvalues': 10.1.11 + dev: false + /@polkadot/wasm-bridge/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-1TYkHsb9AEFhU9uZj3biEnN2yKQNzdrwSjiTvfCYnt97pnEkKsZI6cku+YPZQv5w/x9CQa5Yua9e2DVVZSivGA==} engines: {node: '>=14.0.0'} @@ -2946,6 +3013,16 @@ packages: '@polkadot/util': 10.1.10 dev: false + /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.11: + resolution: {integrity: sha512-zbombRfA5v/mUWQQhgg2YwaxhRmxRIrvskw65x+lruax3b6xPBFDs7yplopiJU3r8h2pTgQvX/DUksvqz2TCRQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@polkadot/util': '*' + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.11 + dev: false + /@polkadot/wasm-crypto-asmjs/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-zbombRfA5v/mUWQQhgg2YwaxhRmxRIrvskw65x+lruax3b6xPBFDs7yplopiJU3r8h2pTgQvX/DUksvqz2TCRQ==} engines: {node: '>=14.0.0'} @@ -2996,6 +3073,21 @@ packages: '@polkadot/x-randomvalues': 10.1.2 dev: false + /@polkadot/wasm-crypto-init/6.3.1_kq5krb3p4bzvrcxi3xa2lgyh6u: + resolution: {integrity: sha512-9yaUBcu+snwjJLmPPGl3cyGRQ1afyFGm16qzTM0sgG/ZCfUlK4uk8KWZe+sBUKgoxb2oXY7Y4WklKgQI1YBdfw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@polkadot/util': '*' + '@polkadot/x-randomvalues': '*' + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.11 + '@polkadot/wasm-bridge': 6.3.1_kq5krb3p4bzvrcxi3xa2lgyh6u + '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.11 + '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.11 + '@polkadot/x-randomvalues': 10.1.11 + dev: false + /@polkadot/wasm-crypto-init/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-9yaUBcu+snwjJLmPPGl3cyGRQ1afyFGm16qzTM0sgG/ZCfUlK4uk8KWZe+sBUKgoxb2oXY7Y4WklKgQI1YBdfw==} engines: {node: '>=14.0.0'} @@ -3052,6 +3144,17 @@ packages: '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.10 dev: false + /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.11: + resolution: {integrity: sha512-idSlzKGVzCfeCMRHsacRvqwojSaTadFxL/Dbls4z1thvfa3U9Ku0d2qVtlwg7Hj+tYWDiuP8Kygs+6bQwfs0XA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@polkadot/util': '*' + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.11 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.11 + dev: false + /@polkadot/wasm-crypto-wasm/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-idSlzKGVzCfeCMRHsacRvqwojSaTadFxL/Dbls4z1thvfa3U9Ku0d2qVtlwg7Hj+tYWDiuP8Kygs+6bQwfs0XA==} engines: {node: '>=14.0.0'} @@ -3150,6 +3253,23 @@ packages: '@polkadot/x-randomvalues': 10.1.2 dev: false + /@polkadot/wasm-crypto/6.3.1_kq5krb3p4bzvrcxi3xa2lgyh6u: + resolution: {integrity: sha512-OO8h0qeVkqp4xYZaRVl4iuWOEtq282pNBHDKb6SOJuI2g59eWGcKh4EQU9Me2VP6qzojIqptrkrVt7KQXC68gA==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@polkadot/util': '*' + '@polkadot/x-randomvalues': '*' + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.11 + '@polkadot/wasm-bridge': 6.3.1_kq5krb3p4bzvrcxi3xa2lgyh6u + '@polkadot/wasm-crypto-asmjs': 6.3.1_@polkadot+util@10.1.11 + '@polkadot/wasm-crypto-init': 6.3.1_kq5krb3p4bzvrcxi3xa2lgyh6u + '@polkadot/wasm-crypto-wasm': 6.3.1_@polkadot+util@10.1.11 + '@polkadot/wasm-util': 6.3.1_@polkadot+util@10.1.11 + '@polkadot/x-randomvalues': 10.1.11 + dev: false + /@polkadot/wasm-crypto/6.3.1_xnbzfk7hwbn2cwqh2nrvbgvkzq: resolution: {integrity: sha512-OO8h0qeVkqp4xYZaRVl4iuWOEtq282pNBHDKb6SOJuI2g59eWGcKh4EQU9Me2VP6qzojIqptrkrVt7KQXC68gA==} engines: {node: '>=14.0.0'} @@ -3177,6 +3297,16 @@ packages: '@polkadot/util': 10.1.10 dev: false + /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.11: + resolution: {integrity: sha512-12oAv5J7Yoc9m6jixrSaQCxpOkWOyzHx3DMC8qmLjRiwdBWxqLmImOVRVnFsbaxqSbhBIHRuJphVxWE+GZETDg==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@polkadot/util': '*' + dependencies: + '@babel/runtime': 7.19.0 + '@polkadot/util': 10.1.11 + dev: false + /@polkadot/wasm-util/6.3.1_@polkadot+util@10.1.2: resolution: {integrity: sha512-12oAv5J7Yoc9m6jixrSaQCxpOkWOyzHx3DMC8qmLjRiwdBWxqLmImOVRVnFsbaxqSbhBIHRuJphVxWE+GZETDg==} engines: {node: '>=14.0.0'} @@ -3213,6 +3343,14 @@ packages: '@polkadot/x-global': 10.1.10 dev: false + /@polkadot/x-bigint/10.1.11: + resolution: {integrity: sha512-TC4KZ+ni/SJhcf/LIwD49C/kwvACu0nCchETNO+sAfJ7COXZwHDUJXVXmwN5PgkQxwsWsKKuJmzR/Fi1bgMWnQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/x-global': 10.1.11 + dev: false + /@polkadot/x-bigint/10.1.2: resolution: {integrity: sha512-TCwv3NjQdfLb7CBYR8EA5t0CrMfYx3IF4hKjctuplL+mDNI0VzNn4qVKW62AjouI8kMbn7VyBPfoBeuYX8Ixrw==} engines: {node: '>=14.0.0'} @@ -3255,6 +3393,16 @@ packages: node-fetch: 3.2.10 dev: false + /@polkadot/x-fetch/10.1.11: + resolution: {integrity: sha512-WtyUr9itVD9BLnxCUloJ1iwrXOY/lnlEShEYKHcSm6MIHtbJolePd3v1+o5mOX+bdDbHXhPZnH8anCCqDNDRqg==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/x-global': 10.1.11 + '@types/node-fetch': 2.6.2 + node-fetch: 3.2.10 + dev: false + /@polkadot/x-fetch/10.1.2: resolution: {integrity: sha512-Zd7npq9H/kDaehiM2iyPX1+cSfuhCvqDxuS8GLTjARIVGGURBfA+NjRM6o6jsXa3HCtv+lB67Qdw1m/PSxfIpQ==} engines: {node: '>=14.0.0'} @@ -3303,6 +3451,13 @@ packages: '@babel/runtime': 7.19.0 dev: false + /@polkadot/x-global/10.1.11: + resolution: {integrity: sha512-bWz5gdcELy6+xfr27R1GE5MPX4nfVlchzHQH+DR6OBbSi9g/PeycQAvFB6IkTmP+YEbNNtIpxnSP37zoUaG3xw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + dev: false + /@polkadot/x-global/10.1.2: resolution: {integrity: sha512-//r3NVLYdYQs0So0IK8Pa0pnL5pPi0geQWE6qjTtPD0oszuN9SUDqDlFQj3I3vqQOwgybbzBGNYRRinP8B2xUg==} engines: {node: '>=14.0.0'} @@ -3353,6 +3508,14 @@ packages: '@polkadot/x-global': 10.1.10 dev: false + /@polkadot/x-randomvalues/10.1.11: + resolution: {integrity: sha512-V2V37f5hoM5B32eCpGw87Lwstin2+ArXhOZ8ENKncbQLXzbF9yTODueDoA5Vt0MJCs2CDP9cyiCYykcanqVkxg==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/x-global': 10.1.11 + dev: false + /@polkadot/x-randomvalues/10.1.2: resolution: {integrity: sha512-KOu6iZWye9KD6qoahiqZ0alrT/5FSGL4XXLhVSg69xAqD6yG2oi2aKA6cZpDU19uZGqVneqsgpebDsrZ0nLUEg==} engines: {node: '>=14.0.0'} @@ -3417,6 +3580,14 @@ packages: '@polkadot/x-global': 10.1.10 dev: false + /@polkadot/x-textdecoder/10.1.11: + resolution: {integrity: sha512-QZqie04SR6pAj260PaLBfZUGXWKI357t4ROVJhpaj06qc1zrk1V8Mwkr49+WzjAPFEOqo70HWnzXmPNCH4dQiw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/x-global': 10.1.11 + dev: false + /@polkadot/x-textdecoder/10.1.2: resolution: {integrity: sha512-liMlSSKfLGTvcUPz1fMicH2HoKLgSjzxFYsbNfXJOe9GobQfSrAOcprM0j4gNJqN5EoZhze9Sf1rMTORQwomtg==} engines: {node: '>=14.0.0'} @@ -3481,6 +3652,14 @@ packages: '@polkadot/x-global': 10.1.10 dev: false + /@polkadot/x-textencoder/10.1.11: + resolution: {integrity: sha512-UX+uV9AbDID81waaG/NvTkkf7ZNVW7HSHaddgbWjQEVW2Ex4ByccBarY5jEi6cErEPKfzCamKhgXflu0aV9LWw==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/x-global': 10.1.11 + dev: false + /@polkadot/x-textencoder/10.1.2: resolution: {integrity: sha512-bSMvesZ43Er6+jogt9IfwWN/E8bhkl4a9nNnpyS/vTh+j6n/DfDQrvYpKDpRIn7oJA6lfs/mL9Jo5jjJTngaxg==} engines: {node: '>=14.0.0'} @@ -3541,6 +3720,18 @@ packages: - supports-color dev: false + /@polkadot/x-ws/10.1.11: + resolution: {integrity: sha512-EUbL/R1A/NxYf6Rnb1M7U9yeTuo5r4y2vcQllE5aBLaQ0cFnRykHzlmZlVX1E7O5uy3lYVdxWC7sNgxItIWkWA==} + engines: {node: '>=14.0.0'} + dependencies: + '@babel/runtime': 7.19.4 + '@polkadot/x-global': 10.1.11 + '@types/websocket': 1.0.5 + websocket: 1.0.34 + transitivePeerDependencies: + - supports-color + dev: false + /@polkadot/x-ws/10.1.2: resolution: {integrity: sha512-RQkc6TPM7xOKHMrE3R/8+FdE9fMGJEN7yfK/GixpMGzw98NcVedxJ1xTL19r76hJvOSeZAEks5oqgMxF8K9Pbg==} engines: {node: '>=14.0.0'} @@ -3672,7 +3863,7 @@ packages: /@subsocial/definitions/0.6.11: resolution: {integrity: sha512-FQDzZmSaHXQ9x5HoudPcDYf3BmH2CN7zPbPZS+01LZXhelDN7qbNk36+pBeXki0zmtUnevWjy6LKld8zZ3XLBw==} dependencies: - '@polkadot/api': 9.5.1 + '@polkadot/api': 9.5.2 lodash.camelcase: 4.3.0 transitivePeerDependencies: - bufferutil @@ -3751,6 +3942,10 @@ packages: resolution: {integrity: sha512-OSOmdjaq9foXfHBy9aLVMwGheygvsiZlv4dggnLOYOuhSmNCsSB/PaW4DBz+/tSdK1Fo9+ZiFW6cF24RA+m0sw==} dev: false + /@substrate/ss58-registry/1.33.0: + resolution: {integrity: sha512-DztMuMcEfu+tJrtIQIIp5gO8/XJZ8N8UwPObDCSNgrp7trtSkPJAUFB9qXaReXtN9UvTcVBMTWk6VPfFi04Wkg==} + dev: false + /@substrate/txwrapper-core/3.1.7: resolution: {integrity: sha512-6HC4ZyOcKRhhTo9leBoksseVXlfUmVIEFjEEF5RFq1YMVMzuO2WE54ocjNHGKGPz+HBOq8DYMpuJ1AqXeM379g==} dependencies: diff --git a/src/contracts/contracts.resolver.ts b/src/contracts/contracts.resolver.ts index 0536fcc..bff7676 100644 --- a/src/contracts/contracts.resolver.ts +++ b/src/contracts/contracts.resolver.ts @@ -3,7 +3,7 @@ import { FetchEventsInput } from '../events/dtos/fetch-events.input' import { Event } from '../events/entity/event.entity' import { EventsService } from '../events/events.service' import { ContractsService } from './contracts.service' -import { Contract } from './entity/contract.entity' +import { Contract, ContractQuery } from './entity/contract.entity' @Resolver(() => Contract) export class ContractsResolver { @@ -14,6 +14,11 @@ export class ContractsResolver { return this.contractsService.findOne(address) } + @Query(/* istanbul ignore next */ () => Contract) + async getContractQueries(@Args('address', { type: () => String }) address: string) { + return this.contractsService.getContractQueries(address) + } + @Mutation(/* istanbul ignore next */ () => Boolean) async uploadMetadata( @Args('metadata', { type: /* istanbul ignore next */ () => String }) metadata: string, @@ -35,4 +40,16 @@ export class ContractsResolver { } return this.eventsService.fetchEvents(args) } + + @ResolveField('queries', /* istanbul ignore next */ () => [ContractQuery]) + async queries(@Parent() contract: Contract) { + const { queries } = contract + if (!queries) { + return [] + } + queries.forEach((query) => { + query.args = query.args.map((arg) => JSON.stringify(arg)) + }) + return queries + } } diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index de0b511..f6202c2 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -1,8 +1,11 @@ import { Injectable, NotFoundException } from '@nestjs/common' import { InjectRepository } from '@nestjs/typeorm' +import { Abi, ContractPromise } from '@polkadot/api-contract' import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import { Repository } from 'typeorm' -import { Contract } from './entity/contract.entity' +import { connect } from '../utils' +import { Contract, ContractQuery } from './entity/contract.entity' +const WS_PROVIDER = process.env.WS_PROVIDER || 'ws://127.0.0.1:9944' @Injectable() export class ContractsService { @@ -33,4 +36,65 @@ export class ContractsService { } return true } + + async getContractQueries(contractAddress: string): Promise { + const api = await connect(WS_PROVIDER) + const contract = await this.findOne(contractAddress) + const { address, metadata } = contract + if (!address || !metadata) { + throw new Error('Contract address or metadata not found') + } + const abi = new Abi(metadata) + const contractPromise = new ContractPromise(api, abi, address) + const contractQueries: ContractQuery[] = [] + Object.keys(contractPromise.query).map((k) => { + const { method, docs, args, identifier } = contractPromise.query[k].meta + contractQueries.push({ + method, + docs, + args, + name: (identifier[0].toUpperCase() + identifier.substring(1)).replace('_', ' '), + }) + }) + contract.queries = contractQueries + return contract + + /*const contractOptions: ContractOptions = { + gasLimit: 200_000_000_000_000, + storageDepositLimit: undefined, + value: undefined, + }*/ + /*const totalSupply = await contractPromise.query.totalSupply(ALICE_ADDRESS, contractOptions) + printResult('totalSupply', totalSupply) + const balanceOf = await contractPromise.query.balanceOf(ALICE_ADDRESS, contractOptions, BOB_ADDRESS) + printResult('balanceOf', balanceOf) + const approve = await contractPromise.query.approve( + ALICE_ADDRESS, + contractOptions, + BOB_ADDRESS, + 1000_000_000_000_000, + ) + printResult('approve', approve) + const allowance = await contractPromise.query.allowance(ALICE_ADDRESS, contractOptions, ALICE_ADDRESS, BOB_ADDRESS) + printResult('allowance', allowance)*/ + } } +/* +const ALICE_ADDRESS = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY' +const BOB_ADDRESS = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty' +const printResult = (method: string, r: any) => { + console.log(`\n${method.toUpperCase()}:`) + const { gasRequired, result, output } = r + console.log('RESULT', result.toHuman()) + + // the gas consumed for contract execution + console.log('GAS REQUIRED', gasRequired.toHuman()) + + // check if the call was successful + if (result.isOk) { + // output the return value + console.log('Success', output?.toHuman()) + } else { + console.log('Error', result.asErr.toHuman()) + } +}*/ diff --git a/src/contracts/entity/contract.entity.ts b/src/contracts/entity/contract.entity.ts index bedbedc..25ade83 100644 --- a/src/contracts/entity/contract.entity.ts +++ b/src/contracts/entity/contract.entity.ts @@ -1,4 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql' +import { AbiParam } from '@polkadot/api-contract/types' import { BaseEntity, Column, CreateDateColumn, Entity, Index, OneToMany, PrimaryColumn } from 'typeorm' import { Event } from '../../events/entity/event.entity' @@ -19,8 +20,26 @@ export class Contract extends BaseEntity { }) events!: Event[] + @Field(/* istanbul ignore next */ () => [ContractQuery]) + queries?: ContractQuery[] + @CreateDateColumn({ default: /* istanbul ignore next */ () => 'NOW()', }) createdDate!: Date } + +@ObjectType() +export class ContractQuery { + @Field(/* istanbul ignore next */ () => String) + name!: string + + @Field(/* istanbul ignore next */ () => String) + method!: string + + @Field(/* istanbul ignore next */ () => [String]) + args!: AbiParam[] | string[] + + @Field(/* istanbul ignore next */ () => [String]) + docs!: string[] +} diff --git a/src/schema.graphql b/src/schema.graphql index cb255e6..48a053c 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -15,6 +15,14 @@ type Contract { address: String! events: [Event!]! metadata: String + queries: [ContractQuery!]! +} + +type ContractQuery { + args: [String!]! + docs: [String!]! + method: String! + name: String! } type Event { @@ -40,6 +48,7 @@ type Query { getBlock(hash: String!): Block! getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! + getContractQueries(address: String!): Contract! getEvent(id: String!): Event! getEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! diff --git a/src/subscriptions/subscriptions.service.ts b/src/subscriptions/subscriptions.service.ts index d4eb28f..4b0139c 100644 --- a/src/subscriptions/subscriptions.service.ts +++ b/src/subscriptions/subscriptions.service.ts @@ -2,13 +2,14 @@ import { Injectable, OnModuleInit } from '@nestjs/common' import '@polkadot/api-augment' -import { ApiPromise, WsProvider } from '@polkadot/api' +import { ApiPromise } from '@polkadot/api' import { BlockHash, Header } from '@polkadot/types/interfaces' import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import PQueue from 'p-queue' import { BlocksService } from '../blocks/blocks.service' import { EventsService } from '../events/events.service' import { TransactionsService } from '../transactions/transactions.service' +import { connect } from '../utils' const retry = require('async-await-retry') const FIRST_BLOCK_TO_LOAD = Number(process.env.FIRST_BLOCK_TO_LOAD) || 0 @@ -36,13 +37,8 @@ export class SubscriptionsService implements OnModuleInit { } } - static async connect(): Promise { - const provider = new WsProvider(WS_PROVIDER) - return ApiPromise.create({ provider }) - } - async syncBlocks() { - const api = await SubscriptionsService.connect() + const api = await connect(WS_PROVIDER) const lastDBBlockNumber = (await this.blocksService.getLastBlock())?.number || 0 const lastBlockNumber = (await api.rpc.chain.getHeader()).number.toNumber() const loadFromBlockNumber = LOAD_ALL_BLOCKS ? FIRST_BLOCK_TO_LOAD : lastDBBlockNumber diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..965012d --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,5 @@ +import { ApiPromise, WsProvider } from '@polkadot/api' + +export const connect = async (provider: string | string[] | undefined) => { + return ApiPromise.create({ provider: new WsProvider(provider) }) +} From 4de988504fc52289da8b4e2bde19de5fd50d1290 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Fri, 21 Oct 2022 12:55:40 -0400 Subject: [PATCH 16/28] execute queries resolver --- src/contracts/contracts.resolver.ts | 8 ++++- src/contracts/contracts.service.ts | 41 ++++++++++++++++++++--- src/contracts/dtos/execute-query.input.ts | 37 ++++++++++++++++++++ src/contracts/entity/contract.entity.ts | 16 +++++++++ src/schema.graphql | 22 ++++++++++++ 5 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 src/contracts/dtos/execute-query.input.ts diff --git a/src/contracts/contracts.resolver.ts b/src/contracts/contracts.resolver.ts index bff7676..da95731 100644 --- a/src/contracts/contracts.resolver.ts +++ b/src/contracts/contracts.resolver.ts @@ -3,7 +3,8 @@ import { FetchEventsInput } from '../events/dtos/fetch-events.input' import { Event } from '../events/entity/event.entity' import { EventsService } from '../events/events.service' import { ContractsService } from './contracts.service' -import { Contract, ContractQuery } from './entity/contract.entity' +import { ExecuteQueryInput } from './dtos/execute-query.input' +import { Contract, ContractQuery, QueryResult } from './entity/contract.entity' @Resolver(() => Contract) export class ContractsResolver { @@ -19,6 +20,11 @@ export class ContractsResolver { return this.contractsService.getContractQueries(address) } + @Query(/* istanbul ignore next */ () => QueryResult) + async executeQuery(@Args() parameters: ExecuteQueryInput) { + return this.contractsService.executeQuery(parameters) + } + @Mutation(/* istanbul ignore next */ () => Boolean) async uploadMetadata( @Args('metadata', { type: /* istanbul ignore next */ () => String }) metadata: string, diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index f6202c2..f7ec434 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -1,10 +1,12 @@ import { Injectable, NotFoundException } from '@nestjs/common' import { InjectRepository } from '@nestjs/typeorm' import { Abi, ContractPromise } from '@polkadot/api-contract' +import { ContractOptions } from '@polkadot/api-contract/types' import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import { Repository } from 'typeorm' import { connect } from '../utils' -import { Contract, ContractQuery } from './entity/contract.entity' +import { ExecuteQueryInput } from './dtos/execute-query.input' +import { Contract, ContractQuery, QueryResult } from './entity/contract.entity' const WS_PROVIDER = process.env.WS_PROVIDER || 'ws://127.0.0.1:9944' @Injectable() @@ -58,13 +60,44 @@ export class ContractsService { }) contract.queries = contractQueries return contract + } - /*const contractOptions: ContractOptions = { + async executeQuery({ address, method, args }: ExecuteQueryInput): Promise { + const api = await connect(WS_PROVIDER) + const contract = await this.findOne(address) + const { metadata } = contract || {} + if (!metadata) { + throw new Error('Contract metadata not found') + } + const abi = new Abi(metadata) + const contractPromise = new ContractPromise(api, abi, address) + const query = contractPromise.query[method] + if (!query) { + throw new Error('Query not found') + } + const { sender, options, values } = args || {} + const { debugMessage, gasConsumed, gasRequired, output, result, storageDeposit } = await query( + sender as string, + options as ContractOptions, + ...(values || []), + ) + return { + debugMessage: debugMessage.toHuman(), + gasConsumed: gasConsumed.toString(), + gasRequired: gasRequired.toString(), + output: output?.toString(), + result: result.toString(), + storageDeposit: storageDeposit.toString(), + } + } +} + +/*const contractOptions: ContractOptions = { gasLimit: 200_000_000_000_000, storageDepositLimit: undefined, value: undefined, }*/ - /*const totalSupply = await contractPromise.query.totalSupply(ALICE_ADDRESS, contractOptions) +/*const totalSupply = await contractPromise.query.totalSupply(ALICE_ADDRESS, contractOptions) printResult('totalSupply', totalSupply) const balanceOf = await contractPromise.query.balanceOf(ALICE_ADDRESS, contractOptions, BOB_ADDRESS) printResult('balanceOf', balanceOf) @@ -77,8 +110,6 @@ export class ContractsService { printResult('approve', approve) const allowance = await contractPromise.query.allowance(ALICE_ADDRESS, contractOptions, ALICE_ADDRESS, BOB_ADDRESS) printResult('allowance', allowance)*/ - } -} /* const ALICE_ADDRESS = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY' const BOB_ADDRESS = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty' diff --git a/src/contracts/dtos/execute-query.input.ts b/src/contracts/dtos/execute-query.input.ts new file mode 100644 index 0000000..c4a6209 --- /dev/null +++ b/src/contracts/dtos/execute-query.input.ts @@ -0,0 +1,37 @@ +import { Field, ArgsType, InputType } from '@nestjs/graphql' + +@InputType() +export class QueryOptions { + @Field(/* istanbul ignore next */ () => String) + gasLimit?: string + + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + storageLimit?: string + + @Field(/* istanbul ignore next */ () => String, { nullable: true }) + value?: string +} + +@InputType() +export class QueryArgs { + @Field(/* istanbul ignore next */ () => String) + sender!: string + + @Field(/* istanbul ignore next */ () => QueryOptions) + options?: QueryOptions + + @Field(/* istanbul ignore next */ () => [String]) + values?: string[] = [] +} + +@ArgsType() +export class ExecuteQueryInput { + @Field(/* istanbul ignore next */ () => String) + address!: string + + @Field(/* istanbul ignore next */ () => String) + method!: string + + @Field(/* istanbul ignore next */ () => QueryArgs) + args?: QueryArgs = { sender: '', options: {}, values: [] } +} diff --git a/src/contracts/entity/contract.entity.ts b/src/contracts/entity/contract.entity.ts index 25ade83..8fe47d7 100644 --- a/src/contracts/entity/contract.entity.ts +++ b/src/contracts/entity/contract.entity.ts @@ -43,3 +43,19 @@ export class ContractQuery { @Field(/* istanbul ignore next */ () => [String]) docs!: string[] } + +@ObjectType() +export class QueryResult { + @Field(/* istanbul ignore next */ () => String) + debugMessage?: string + @Field(/* istanbul ignore next */ () => String) + gasConsumed?: string + @Field(/* istanbul ignore next */ () => String) + gasRequired?: string + @Field(/* istanbul ignore next */ () => String) + output?: string + @Field(/* istanbul ignore next */ () => String) + result?: string + @Field(/* istanbul ignore next */ () => String) + storageDeposit?: string +} diff --git a/src/schema.graphql b/src/schema.graphql index 48a053c..29f5e53 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -45,6 +45,7 @@ type Mutation { type Query { decodeEvent(contractAddress: String!, id: String!): String! decodeEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): String! + executeQuery(address: String!, args: QueryArgs = {options: {}, sender: "", values: []}, method: String!): QueryResult! getBlock(hash: String!): Block! getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! @@ -58,6 +59,27 @@ type Query { version: String! } +input QueryArgs { + options: QueryOptions! + sender: String! + values: [String!] = [] +} + +input QueryOptions { + gasLimit: String! + storageLimit: String + value: String +} + +type QueryResult { + debugMessage: String! + gasConsumed: String! + gasRequired: String! + output: String! + result: String! + storageDeposit: String! +} + type Transaction { args: String blockHash: String From a47cde59476d3269c472014fe931a792d4c8df6a Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Sun, 23 Oct 2022 03:39:34 -0400 Subject: [PATCH 17/28] execute queries resolver --- src/contracts/contracts.resolver.ts | 2 +- src/contracts/contracts.service.ts | 16 +++++++++------- src/schema.graphql | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/contracts/contracts.resolver.ts b/src/contracts/contracts.resolver.ts index da95731..1670e11 100644 --- a/src/contracts/contracts.resolver.ts +++ b/src/contracts/contracts.resolver.ts @@ -20,7 +20,7 @@ export class ContractsResolver { return this.contractsService.getContractQueries(address) } - @Query(/* istanbul ignore next */ () => QueryResult) + @Mutation(/* istanbul ignore next */ () => QueryResult) async executeQuery(@Args() parameters: ExecuteQueryInput) { return this.contractsService.executeQuery(parameters) } diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index f7ec434..02f667c 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -44,7 +44,9 @@ export class ContractsService { const contract = await this.findOne(contractAddress) const { address, metadata } = contract if (!address || !metadata) { - throw new Error('Contract address or metadata not found') + this.logger.warn('Contract address or metadata not found') + contract.queries = [] + return contract } const abi = new Abi(metadata) const contractPromise = new ContractPromise(api, abi, address) @@ -82,12 +84,12 @@ export class ContractsService { ...(values || []), ) return { - debugMessage: debugMessage.toHuman(), - gasConsumed: gasConsumed.toString(), - gasRequired: gasRequired.toString(), - output: output?.toString(), - result: result.toString(), - storageDeposit: storageDeposit.toString(), + debugMessage: debugMessage.toHuman() || '', + gasConsumed: gasConsumed.toString() || '', + gasRequired: gasRequired.toString() || '', + output: output?.toString() || '', + result: result.toString() || '', + storageDeposit: storageDeposit.toString() || '', } } } diff --git a/src/schema.graphql b/src/schema.graphql index 29f5e53..46aa319 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -39,13 +39,13 @@ type Event { } type Mutation { + executeQuery(address: String!, args: QueryArgs = {options: {}, sender: "", values: []}, method: String!): QueryResult! uploadMetadata(contractAddress: String!, metadata: String!): Boolean! } type Query { decodeEvent(contractAddress: String!, id: String!): String! decodeEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): String! - executeQuery(address: String!, args: QueryArgs = {options: {}, sender: "", values: []}, method: String!): QueryResult! getBlock(hash: String!): Block! getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! From a57109ecf09339832deeaab42710508e2f3f6342 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Sun, 23 Oct 2022 16:49:05 -0400 Subject: [PATCH 18/28] get contracts resolver --- src/contracts/contracts.resolver.ts | 12 ++++++++++++ src/contracts/contracts.service.ts | 9 +++++++++ src/contracts/dtos/fetch-contracts.input.ts | 11 +++++++++++ src/schema.graphql | 2 ++ 4 files changed, 34 insertions(+) create mode 100644 src/contracts/dtos/fetch-contracts.input.ts diff --git a/src/contracts/contracts.resolver.ts b/src/contracts/contracts.resolver.ts index 1670e11..2be31f5 100644 --- a/src/contracts/contracts.resolver.ts +++ b/src/contracts/contracts.resolver.ts @@ -4,6 +4,7 @@ import { Event } from '../events/entity/event.entity' import { EventsService } from '../events/events.service' import { ContractsService } from './contracts.service' import { ExecuteQueryInput } from './dtos/execute-query.input' +import { FetchContractsInput } from './dtos/fetch-contracts.input' import { Contract, ContractQuery, QueryResult } from './entity/contract.entity' @Resolver(() => Contract) @@ -15,6 +16,11 @@ export class ContractsResolver { return this.contractsService.findOne(address) } + @Query(/* istanbul ignore next */ () => [Contract]) + async getContracts(@Args() args: FetchContractsInput) { + return this.contractsService.fetchContracts(args) + } + @Query(/* istanbul ignore next */ () => Contract) async getContractQueries(@Args('address', { type: () => String }) address: string) { return this.contractsService.getContractQueries(address) @@ -58,4 +64,10 @@ export class ContractsResolver { }) return queries } + + @ResolveField('hasMetadata', /* istanbul ignore next */ () => Boolean) + async hasMetadata(@Parent() contract: Contract) { + const { metadata } = contract + return !!metadata + } } diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index 02f667c..84d743d 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -6,6 +6,7 @@ import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import { Repository } from 'typeorm' import { connect } from '../utils' import { ExecuteQueryInput } from './dtos/execute-query.input' +import { FetchContractsInput } from './dtos/fetch-contracts.input' import { Contract, ContractQuery, QueryResult } from './entity/contract.entity' const WS_PROVIDER = process.env.WS_PROVIDER || 'ws://127.0.0.1:9944' @@ -26,6 +27,14 @@ export class ContractsService { return contract } + async fetchContracts(args: FetchContractsInput): Promise { + const { skip, take } = args + return this.contractRepository.find({ + skip, + take, + }) + } + async uploadMetadata(contract: Contract, metadata: string): Promise { try { const buff = Buffer.from(metadata, 'base64') diff --git a/src/contracts/dtos/fetch-contracts.input.ts b/src/contracts/dtos/fetch-contracts.input.ts new file mode 100644 index 0000000..060adee --- /dev/null +++ b/src/contracts/dtos/fetch-contracts.input.ts @@ -0,0 +1,11 @@ +import { Field, Int, ArgsType } from '@nestjs/graphql' + +@ArgsType() +export class FetchContractsInput { + @Field(/* istanbul ignore next */ () => Int) + skip? = 0 + + @Field(/* istanbul ignore next */ () => Int) + take? = 20 + +} diff --git a/src/schema.graphql b/src/schema.graphql index 46aa319..26a660b 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -14,6 +14,7 @@ type Block { type Contract { address: String! events: [Event!]! + hasMetadata: Boolean! metadata: String queries: [ContractQuery!]! } @@ -50,6 +51,7 @@ type Query { getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! getContractQueries(address: String!): Contract! + getContracts(skip: Int = 0, take: Int = 20): [Contract!]! getEvent(id: String!): Event! getEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): [Event!]! getTransaction(hash: String!): Transaction! From 53803d95f4ab6e05fa9d68a6184e773d005b2a09 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Sun, 23 Oct 2022 22:08:04 -0400 Subject: [PATCH 19/28] decode events to mutiation --- src/events/events.resolver.ts | 6 +++--- src/schema.graphql | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/events/events.resolver.ts b/src/events/events.resolver.ts index f1efbae..c6650c1 100644 --- a/src/events/events.resolver.ts +++ b/src/events/events.resolver.ts @@ -1,4 +1,4 @@ -import { Args, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql' +import { Args, Mutation, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql' import { FetchEventsInput } from './dtos/fetch-events.input' import { Event } from './entity/event.entity' import { EventsService } from './events.service' @@ -16,7 +16,7 @@ export class EventsResolver { return this.eventsService.findById(id) } - @Query(/* istanbul ignore next */ () => String) + @Mutation(/* istanbul ignore next */ () => String) async decodeEvents(@Args() args: FetchEventsInput) { try { const events = await this.eventsService.fetchEvents(args) @@ -27,7 +27,7 @@ export class EventsResolver { } } - @Query(/* istanbul ignore next */ () => String) + @Mutation(/* istanbul ignore next */ () => String) async decodeEvent( @Args('contractAddress', { type: () => String }) contractAddress: string, @Args('id', { type: () => String }) id: string, diff --git a/src/schema.graphql b/src/schema.graphql index 26a660b..0167483 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -40,13 +40,13 @@ type Event { } type Mutation { + decodeEvent(contractAddress: String!, id: String!): String! + decodeEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): String! executeQuery(address: String!, args: QueryArgs = {options: {}, sender: "", values: []}, method: String!): QueryResult! uploadMetadata(contractAddress: String!, metadata: String!): Boolean! } type Query { - decodeEvent(contractAddress: String!, id: String!): String! - decodeEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): String! getBlock(hash: String!): Block! getBlocks(orderAsc: Boolean = false, orderByNumber: Boolean = false, skip: Int = 0, take: Int = 10): [Block!]! getContract(address: String!): Contract! From fb45676e46c14153a86d337bda694265d82de152 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Mon, 24 Oct 2022 18:42:46 -0400 Subject: [PATCH 20/28] decode events result --- src/contracts/contracts.resolver.ts | 8 +-- src/contracts/contracts.service.ts | 71 +---------------------- src/contracts/dtos/execute-query.input.ts | 37 ------------ src/events/events.service.ts | 2 +- src/schema.graphql | 22 ------- 5 files changed, 3 insertions(+), 137 deletions(-) delete mode 100644 src/contracts/dtos/execute-query.input.ts diff --git a/src/contracts/contracts.resolver.ts b/src/contracts/contracts.resolver.ts index 2be31f5..616de33 100644 --- a/src/contracts/contracts.resolver.ts +++ b/src/contracts/contracts.resolver.ts @@ -3,9 +3,8 @@ import { FetchEventsInput } from '../events/dtos/fetch-events.input' import { Event } from '../events/entity/event.entity' import { EventsService } from '../events/events.service' import { ContractsService } from './contracts.service' -import { ExecuteQueryInput } from './dtos/execute-query.input' import { FetchContractsInput } from './dtos/fetch-contracts.input' -import { Contract, ContractQuery, QueryResult } from './entity/contract.entity' +import { Contract, ContractQuery } from './entity/contract.entity' @Resolver(() => Contract) export class ContractsResolver { @@ -26,11 +25,6 @@ export class ContractsResolver { return this.contractsService.getContractQueries(address) } - @Mutation(/* istanbul ignore next */ () => QueryResult) - async executeQuery(@Args() parameters: ExecuteQueryInput) { - return this.contractsService.executeQuery(parameters) - } - @Mutation(/* istanbul ignore next */ () => Boolean) async uploadMetadata( @Args('metadata', { type: /* istanbul ignore next */ () => String }) metadata: string, diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index 84d743d..2d8d3dc 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -1,13 +1,11 @@ import { Injectable, NotFoundException } from '@nestjs/common' import { InjectRepository } from '@nestjs/typeorm' import { Abi, ContractPromise } from '@polkadot/api-contract' -import { ContractOptions } from '@polkadot/api-contract/types' import { InjectPinoLogger, PinoLogger } from 'nestjs-pino' import { Repository } from 'typeorm' import { connect } from '../utils' -import { ExecuteQueryInput } from './dtos/execute-query.input' import { FetchContractsInput } from './dtos/fetch-contracts.input' -import { Contract, ContractQuery, QueryResult } from './entity/contract.entity' +import { Contract, ContractQuery } from './entity/contract.entity' const WS_PROVIDER = process.env.WS_PROVIDER || 'ws://127.0.0.1:9944' @Injectable() @@ -72,71 +70,4 @@ export class ContractsService { contract.queries = contractQueries return contract } - - async executeQuery({ address, method, args }: ExecuteQueryInput): Promise { - const api = await connect(WS_PROVIDER) - const contract = await this.findOne(address) - const { metadata } = contract || {} - if (!metadata) { - throw new Error('Contract metadata not found') - } - const abi = new Abi(metadata) - const contractPromise = new ContractPromise(api, abi, address) - const query = contractPromise.query[method] - if (!query) { - throw new Error('Query not found') - } - const { sender, options, values } = args || {} - const { debugMessage, gasConsumed, gasRequired, output, result, storageDeposit } = await query( - sender as string, - options as ContractOptions, - ...(values || []), - ) - return { - debugMessage: debugMessage.toHuman() || '', - gasConsumed: gasConsumed.toString() || '', - gasRequired: gasRequired.toString() || '', - output: output?.toString() || '', - result: result.toString() || '', - storageDeposit: storageDeposit.toString() || '', - } - } } - -/*const contractOptions: ContractOptions = { - gasLimit: 200_000_000_000_000, - storageDepositLimit: undefined, - value: undefined, - }*/ -/*const totalSupply = await contractPromise.query.totalSupply(ALICE_ADDRESS, contractOptions) - printResult('totalSupply', totalSupply) - const balanceOf = await contractPromise.query.balanceOf(ALICE_ADDRESS, contractOptions, BOB_ADDRESS) - printResult('balanceOf', balanceOf) - const approve = await contractPromise.query.approve( - ALICE_ADDRESS, - contractOptions, - BOB_ADDRESS, - 1000_000_000_000_000, - ) - printResult('approve', approve) - const allowance = await contractPromise.query.allowance(ALICE_ADDRESS, contractOptions, ALICE_ADDRESS, BOB_ADDRESS) - printResult('allowance', allowance)*/ -/* -const ALICE_ADDRESS = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY' -const BOB_ADDRESS = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty' -const printResult = (method: string, r: any) => { - console.log(`\n${method.toUpperCase()}:`) - const { gasRequired, result, output } = r - console.log('RESULT', result.toHuman()) - - // the gas consumed for contract execution - console.log('GAS REQUIRED', gasRequired.toHuman()) - - // check if the call was successful - if (result.isOk) { - // output the return value - console.log('Success', output?.toHuman()) - } else { - console.log('Error', result.asErr.toHuman()) - } -}*/ diff --git a/src/contracts/dtos/execute-query.input.ts b/src/contracts/dtos/execute-query.input.ts deleted file mode 100644 index c4a6209..0000000 --- a/src/contracts/dtos/execute-query.input.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Field, ArgsType, InputType } from '@nestjs/graphql' - -@InputType() -export class QueryOptions { - @Field(/* istanbul ignore next */ () => String) - gasLimit?: string - - @Field(/* istanbul ignore next */ () => String, { nullable: true }) - storageLimit?: string - - @Field(/* istanbul ignore next */ () => String, { nullable: true }) - value?: string -} - -@InputType() -export class QueryArgs { - @Field(/* istanbul ignore next */ () => String) - sender!: string - - @Field(/* istanbul ignore next */ () => QueryOptions) - options?: QueryOptions - - @Field(/* istanbul ignore next */ () => [String]) - values?: string[] = [] -} - -@ArgsType() -export class ExecuteQueryInput { - @Field(/* istanbul ignore next */ () => String) - address!: string - - @Field(/* istanbul ignore next */ () => String) - method!: string - - @Field(/* istanbul ignore next */ () => QueryArgs) - args?: QueryArgs = { sender: '', options: {}, values: [] } -} diff --git a/src/events/events.service.ts b/src/events/events.service.ts index 86d3da2..9850606 100644 --- a/src/events/events.service.ts +++ b/src/events/events.service.ts @@ -91,7 +91,7 @@ export class EventsService { const decodedEvent = this.decodeContractEmittedEvent(contract.metadata as string, event.data) event.decodedData = decodedEvent await this.eventRepository.update(event.id, event) - return decodedEvent + return { decodedData: decodedEvent, formattedData: this.formatDecoded(decodedEvent) } } catch (error) { this.logger.error(error) return { message: "Can't decode event", error } diff --git a/src/schema.graphql b/src/schema.graphql index 0167483..c2ae06b 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -42,7 +42,6 @@ type Event { type Mutation { decodeEvent(contractAddress: String!, id: String!): String! decodeEvents(contract: String, orderAsc: Boolean = false, skip: Int = 0, take: Int = 20, transactionHash: String): String! - executeQuery(address: String!, args: QueryArgs = {options: {}, sender: "", values: []}, method: String!): QueryResult! uploadMetadata(contractAddress: String!, metadata: String!): Boolean! } @@ -61,27 +60,6 @@ type Query { version: String! } -input QueryArgs { - options: QueryOptions! - sender: String! - values: [String!] = [] -} - -input QueryOptions { - gasLimit: String! - storageLimit: String - value: String -} - -type QueryResult { - debugMessage: String! - gasConsumed: String! - gasRequired: String! - output: String! - result: String! - storageDeposit: String! -} - type Transaction { args: String blockHash: String From 0eaa1d0a86b25dcd5ddc67387fcf56ea90a4c0e1 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Tue, 25 Oct 2022 14:09:59 -0400 Subject: [PATCH 21/28] events check for existing --- src/events/events.service.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/events/events.service.ts b/src/events/events.service.ts index 9850606..76f36e1 100644 --- a/src/events/events.service.ts +++ b/src/events/events.service.ts @@ -78,7 +78,15 @@ export class EventsService { timestamp, }) }) - return Promise.all(eventsToSave.map((event) => this.eventRepository.save(event))) + return Promise.all( + eventsToSave.map(async (e) => { + let event = (await this.eventRepository.findOne({ where: { id: e.id } })) as Event + if (!event) { + event = (await this.eventRepository.save(e)) as Event + } + return event + }), + ) } async decodeEvents(events: Event[], contractAddress: string) { From 7b5ca300e4bc1d2f603222ed9c3b34a31b92d943 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Wed, 26 Oct 2022 15:35:07 -0400 Subject: [PATCH 22/28] fix tests --- mocks/blocks-mocks.ts | 1 + src/blocks/blocks.service.spec.ts | 6 ++++-- src/events/events.resolver.spec.ts | 16 +++++++++++++--- src/events/events.service.spec.ts | 4 +++- src/subscriptions/subscriptions.service.spec.ts | 7 +++++-- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/mocks/blocks-mocks.ts b/mocks/blocks-mocks.ts index 4d726c2..9ce2a12 100644 --- a/mocks/blocks-mocks.ts +++ b/mocks/blocks-mocks.ts @@ -3,6 +3,7 @@ export const mockBlock = { parentHash: '0x9b0f818b9cac7d9451819de6172e308d67c4b8ff8c2f1f6773cdb20c40573858', number: 27, timestamp: 1590000000, + encodedLength: 100, createdDate: '2022-08-25 22:49:21.843575', } diff --git a/src/blocks/blocks.service.spec.ts b/src/blocks/blocks.service.spec.ts index cec3101..bca7250 100644 --- a/src/blocks/blocks.service.spec.ts +++ b/src/blocks/blocks.service.spec.ts @@ -84,6 +84,7 @@ describe('BlocksService', () => { number, } as any) || {}, mockBlock.timestamp, + mockBlock.encodedLength, ), ).resolves.toBe(mockBlock) expect(repo.create).toBeCalledTimes(1) @@ -92,9 +93,8 @@ describe('BlocksService', () => { parentHash: mockBlock.parentHash, number: mockBlock.number, timestamp: mockBlock.timestamp, + encodedLength: mockBlock.encodedLength, }) - // TODO: fix repo.save called - // expect(repo.save).toBeCalledTimes(1) }) it('should return an existing block', () => { @@ -112,6 +112,7 @@ describe('BlocksService', () => { number, } as any) || {}, mockBlock.timestamp, + mockBlock.encodedLength, ), ).resolves.toBe(mockBlock) expect(repo.create).toBeCalledTimes(1) @@ -119,6 +120,7 @@ describe('BlocksService', () => { hash: mockBlock.hash, parentHash: mockBlock.parentHash, number: mockBlock.number, + encodedLength: mockBlock.encodedLength, timestamp: mockBlock.timestamp, }) expect(repo.save).toBeCalledTimes(0) diff --git a/src/events/events.resolver.spec.ts b/src/events/events.resolver.spec.ts index fa6cf76..b0e156a 100644 --- a/src/events/events.resolver.spec.ts +++ b/src/events/events.resolver.spec.ts @@ -1,6 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing' import { mockDecodedEvent, mockEvents } from '../../mocks/events-mocks' import { EventsService } from '../events/events.service' +import { FetchEventsInput } from './dtos/fetch-events.input' import { EventsResolver } from './events.resolver' describe('EventsResolver', () => { @@ -42,13 +43,22 @@ describe('EventsResolver', () => { describe('decodeEvents', () => { it('should return decoded events for a contract address', () => { - expect(resolver.decodeEvents(mockEvents[0].contractAddress)).resolves.toEqual(JSON.stringify(mockDecodedEvent)) + const args: FetchEventsInput = { + skip: 0, + take: 10, + contract: mockEvents[0].contractAddress, + } + expect(resolver.decodeEvents(args)).resolves.toEqual(JSON.stringify(mockDecodedEvent)) }) it('should return an error message', () => { + const args: FetchEventsInput = { + skip: 0, + take: 10, + contract: mockEvents[0].contractAddress, + } jest.spyOn(eventService, 'decodeEvents').mockRejectedValue(Promise.reject('Contract not found')) - - expect(resolver.decodeEvents(mockEvents[0].contractAddress)).rejects.toBe('Contract not found') + expect(resolver.decodeEvents(args)).rejects.toBe('Contract not found') }) }) diff --git a/src/events/events.service.spec.ts b/src/events/events.service.spec.ts index 9fa1869..f3c5835 100644 --- a/src/events/events.service.spec.ts +++ b/src/events/events.service.spec.ts @@ -24,6 +24,7 @@ describe('EventsService', () => { { provide: getRepositoryToken(Event), useValue: { + findOne: jest.fn().mockResolvedValue(null), findOneBy: jest.fn().mockResolvedValue(mockEvents[0]), find: jest.fn().mockResolvedValue(mockEvents), create: jest.fn().mockResolvedValue(mockEvents[0]), @@ -113,7 +114,8 @@ describe('EventsService', () => { .spyOn(repo, 'save') .mockResolvedValueOnce(mockEvents[0] as never) .mockResolvedValueOnce(mockEvents[1] as never) - + jest.spyOn(repo, 'findOne').mockResolvedValueOnce(null).mockResolvedValueOnce(null) + console.log(repo.findOne) const events = await service.createEventsFromRecords( mockRecords as any, 1, diff --git a/src/subscriptions/subscriptions.service.spec.ts b/src/subscriptions/subscriptions.service.spec.ts index 4d13370..6712f85 100644 --- a/src/subscriptions/subscriptions.service.spec.ts +++ b/src/subscriptions/subscriptions.service.spec.ts @@ -8,8 +8,10 @@ import { mockExtrinsics, mockTimestamp, mockTransactions } from '../../mocks/tra import { BlocksService } from '../blocks/blocks.service' import { EventsService } from '../events/events.service' import { TransactionsService } from '../transactions/transactions.service' +import { connect } from '../utils' import { SubscriptionsService } from './subscriptions.service' jest.mock('@polkadot/api') +jest.mock('../utils') describe('subscriptionsService', () => { let service: SubscriptionsService @@ -20,6 +22,9 @@ describe('subscriptionsService', () => { const MockedApi = ApiPromise as jest.MockedClass MockedApi.create = jest.fn().mockResolvedValue(apiMock) api = await MockedApi.create() + + const mockedConnect = connect as jest.MockedFunction + mockedConnect.mockResolvedValue(api) }) beforeEach(async () => { @@ -75,7 +80,6 @@ describe('subscriptionsService', () => { describe('syncBlocks', () => { it('should load all blocks', async () => { - jest.spyOn(SubscriptionsService, 'connect').mockImplementation(() => Promise.resolve(api)) jest.spyOn(blockService, 'getLastBlock').mockResolvedValue({ ...mockBlock, number: 20 } as any) jest.spyOn(service, 'subscribeNewHeads').mockImplementation(() => Promise.resolve([]) as any) jest @@ -91,7 +95,6 @@ describe('subscriptionsService', () => { }) it('should show already sync message', async () => { - jest.spyOn(SubscriptionsService, 'connect').mockImplementation(() => Promise.resolve(api)) jest.spyOn(blockService, 'getLastBlock').mockResolvedValue({ ...mockBlock, number: 100 } as any) jest.spyOn(service, 'subscribeNewHeads').mockImplementation(() => Promise.resolve([]) as any) From 4b12c479b3b486b87b13b829f5629bf188d416a5 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Wed, 26 Oct 2022 16:41:39 -0400 Subject: [PATCH 23/28] increasing coverage --- mocks/base64-metadata.mock.ts | 2 ++ mocks/contracts-mocks.ts | 7 ++++++ mocks/transactions-mock.ts | 15 +++++++++++++ src/app.resolver.spec.ts | 6 +++++ src/contracts/contracts.resolver.spec.ts | 22 ++++++++++++++++++- src/contracts/contracts.service.spec.ts | 13 +++++++---- src/contracts/entity/contract.entity.ts | 16 -------------- src/events/events.resolver.spec.ts | 16 +++++++++++++- src/events/events.service.spec.ts | 1 - .../subscriptions.service.spec.ts | 1 - src/transactions/transactions.service.ts | 17 +++++++------- 11 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 mocks/base64-metadata.mock.ts diff --git a/mocks/base64-metadata.mock.ts b/mocks/base64-metadata.mock.ts new file mode 100644 index 0000000..f83be65 --- /dev/null +++ b/mocks/base64-metadata.mock.ts @@ -0,0 +1,2 @@ +export const BASE64_METADATA = + 'ewogICJzb3VyY2UiOiB7CiAgICAiaGFzaCI6ICIweDNhYTFjOGJhNWY1OTAzNGE0MmE5M2MwMGVlMDM5YTk0NjRkNmZhNjNkNzBiNjg4OWEyNTk2ZjQ1MjhiMjhhMTkiLAogICAgImxhbmd1YWdlIjogImluayEgMy4zLjAiLAogICAgImNvbXBpbGVyIjogInJ1c3RjIDEuNjQuMC1uaWdodGx5IgogIH0sCiAgImNvbnRyYWN0IjogewogICAgIm5hbWUiOiAiZXJjMjAiLAogICAgInZlcnNpb24iOiAiMC4xLjAiLAogICAgImF1dGhvcnMiOiBbIlt5b3VyX25hbWVdIDxbeW91cl9lbWFpbF0+Il0KICB9LAogICJWMyI6IHsKICAgICJzcGVjIjogewogICAgICAiY29uc3RydWN0b3JzIjogWwogICAgICAgIHsKICAgICAgICAgICJhcmdzIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImxhYmVsIjogImluaXRpYWxfc3VwcGx5IiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQmFsYW5jZSJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAwCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgImRvY3MiOiBbIkNyZWF0ZXMgYSBuZXcgRVJDLTIwIGNvbnRyYWN0IHdpdGggdGhlIHNwZWNpZmllZCBpbml0aWFsIHN1cHBseS4iXSwKICAgICAgICAgICJsYWJlbCI6ICJuZXciLAogICAgICAgICAgInBheWFibGUiOiBmYWxzZSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweDliYWU5ZDVlIgogICAgICAgIH0KICAgICAgXSwKICAgICAgImRvY3MiOiBbXSwKICAgICAgImV2ZW50cyI6IFsKICAgICAgICB7CiAgICAgICAgICAiYXJncyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICJkb2NzIjogW10sCiAgICAgICAgICAgICAgImluZGV4ZWQiOiB0cnVlLAogICAgICAgICAgICAgICJsYWJlbCI6ICJmcm9tIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiT3B0aW9uIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDExCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImRvY3MiOiBbXSwKICAgICAgICAgICAgICAiaW5kZXhlZCI6IHRydWUsCiAgICAgICAgICAgICAgImxhYmVsIjogInRvIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiT3B0aW9uIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDExCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImRvY3MiOiBbXSwKICAgICAgICAgICAgICAiaW5kZXhlZCI6IGZhbHNlLAogICAgICAgICAgICAgICJsYWJlbCI6ICJ2YWx1ZSIsCiAgICAgICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIkJhbGFuY2UiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJkb2NzIjogWyIgRXZlbnQgZW1pdHRlZCB3aGVuIGEgdG9rZW4gdHJhbnNmZXIgb2NjdXJzLiJdLAogICAgICAgICAgImxhYmVsIjogIlRyYW5zZmVyIgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAiZG9jcyI6IFtdLAogICAgICAgICAgICAgICJpbmRleGVkIjogdHJ1ZSwKICAgICAgICAgICAgICAibGFiZWwiOiAib3duZXIiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJkb2NzIjogW10sCiAgICAgICAgICAgICAgImluZGV4ZWQiOiB0cnVlLAogICAgICAgICAgICAgICJsYWJlbCI6ICJzcGVuZGVyIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQWNjb3VudElkIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAiZG9jcyI6IFtdLAogICAgICAgICAgICAgICJpbmRleGVkIjogZmFsc2UsCiAgICAgICAgICAgICAgImxhYmVsIjogInZhbHVlIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQmFsYW5jZSJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAwCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgImRvY3MiOiBbCiAgICAgICAgICAgICIgRXZlbnQgZW1pdHRlZCB3aGVuIGFuIGFwcHJvdmFsIG9jY3VycyB0aGF0IGBzcGVuZGVyYCBpcyBhbGxvd2VkIHRvIHdpdGhkcmF3IiwKICAgICAgICAgICAgIiB1cCB0byB0aGUgYW1vdW50IG9mIGB2YWx1ZWAgdG9rZW5zIGZyb20gYG93bmVyYC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogIkFwcHJvdmFsIgogICAgICAgIH0KICAgICAgXSwKICAgICAgIm1lc3NhZ2VzIjogWwogICAgICAgIHsKICAgICAgICAgICJhcmdzIjogW10sCiAgICAgICAgICAiZG9jcyI6IFsiIFJldHVybnMgdGhlIHRvdGFsIHRva2VuIHN1cHBseS4iXSwKICAgICAgICAgICJsYWJlbCI6ICJ0b3RhbF9zdXBwbHkiLAogICAgICAgICAgIm11dGF0ZXMiOiBmYWxzZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgfSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweGRiNjM3NWE4IgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAib3duZXIiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJkb2NzIjogWwogICAgICAgICAgICAiIFJldHVybnMgdGhlIGFjY291bnQgYmFsYW5jZSBmb3IgdGhlIHNwZWNpZmllZCBgb3duZXJgLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIFJldHVybnMgYDBgIGlmIHRoZSBhY2NvdW50IGlzIG5vbi1leGlzdGVudC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogImJhbGFuY2Vfb2YiLAogICAgICAgICAgIm11dGF0ZXMiOiBmYWxzZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgfSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweDBmNzU1YTU2IgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAib3duZXIiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJzcGVuZGVyIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQWNjb3VudElkIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIF0sCiAgICAgICAgICAiZG9jcyI6IFsKICAgICAgICAgICAgIiBSZXR1cm5zIHRoZSBhbW91bnQgd2hpY2ggYHNwZW5kZXJgIGlzIHN0aWxsIGFsbG93ZWQgdG8gd2l0aGRyYXcgZnJvbSBgb3duZXJgLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIFJldHVybnMgYDBgIGlmIG5vIGFsbG93YW5jZSBoYXMgYmVlbiBzZXQuIgogICAgICAgICAgXSwKICAgICAgICAgICJsYWJlbCI6ICJhbGxvd2FuY2UiLAogICAgICAgICAgIm11dGF0ZXMiOiBmYWxzZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgfSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweDZhMDAxNjVlIgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAidG8iLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJ2YWx1ZSIsCiAgICAgICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIkJhbGFuY2UiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJkb2NzIjogWwogICAgICAgICAgICAiIFRyYW5zZmVycyBgdmFsdWVgIGFtb3VudCBvZiB0b2tlbnMgZnJvbSB0aGUgY2FsbGVyJ3MgYWNjb3VudCB0byBhY2NvdW50IGB0b2AuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgT24gc3VjY2VzcyBhIGBUcmFuc2ZlcmAgZXZlbnQgaXMgZW1pdHRlZC4iLAogICAgICAgICAgICAiIiwKICAgICAgICAgICAgIiAjIEVycm9ycyIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIFJldHVybnMgYEluc3VmZmljaWVudEJhbGFuY2VgIGVycm9yIGlmIHRoZXJlIGFyZSBub3QgZW5vdWdoIHRva2VucyBvbiIsCiAgICAgICAgICAgICIgdGhlIGNhbGxlcidzIGFjY291bnQgYmFsYW5jZS4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogInRyYW5zZmVyIiwKICAgICAgICAgICJtdXRhdGVzIjogdHJ1ZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJSZXN1bHQiXSwKICAgICAgICAgICAgInR5cGUiOiA4CiAgICAgICAgICB9LAogICAgICAgICAgInNlbGVjdG9yIjogIjB4ODRhMTVkYTEiCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAiYXJncyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJzcGVuZGVyIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQWNjb3VudElkIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAidmFsdWUiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDAKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIF0sCiAgICAgICAgICAiZG9jcyI6IFsKICAgICAgICAgICAgIiBBbGxvd3MgYHNwZW5kZXJgIHRvIHdpdGhkcmF3IGZyb20gdGhlIGNhbGxlcidzIGFjY291bnQgbXVsdGlwbGUgdGltZXMsIHVwIHRvIiwKICAgICAgICAgICAgIiB0aGUgYHZhbHVlYCBhbW91bnQuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgSWYgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWdhaW4gaXQgb3ZlcndyaXRlcyB0aGUgY3VycmVudCBhbGxvd2FuY2Ugd2l0aCBgdmFsdWVgLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIEFuIGBBcHByb3ZhbGAgZXZlbnQgaXMgZW1pdHRlZC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogImFwcHJvdmUiLAogICAgICAgICAgIm11dGF0ZXMiOiB0cnVlLAogICAgICAgICAgInBheWFibGUiOiBmYWxzZSwKICAgICAgICAgICJyZXR1cm5UeXBlIjogewogICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIlJlc3VsdCJdLAogICAgICAgICAgICAidHlwZSI6IDgKICAgICAgICAgIH0sCiAgICAgICAgICAic2VsZWN0b3IiOiAiMHg2ODEyNjZhMCIKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJhcmdzIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImxhYmVsIjogImZyb20iLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJ0byIsCiAgICAgICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIkFjY291bnRJZCJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAyCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImxhYmVsIjogInZhbHVlIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQmFsYW5jZSJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAwCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgImRvY3MiOiBbCiAgICAgICAgICAgICIgVHJhbnNmZXJzIGB2YWx1ZWAgdG9rZW5zIG9uIHRoZSBiZWhhbGYgb2YgYGZyb21gIHRvIHRoZSBhY2NvdW50IGB0b2AuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgVGhpcyBjYW4gYmUgdXNlZCB0byBhbGxvdyBhIGNvbnRyYWN0IHRvIHRyYW5zZmVyIHRva2VucyBvbiBvbmVzIGJlaGFsZiBhbmQvb3IiLAogICAgICAgICAgICAiIHRvIGNoYXJnZSBmZWVzIGluIHN1Yi1jdXJyZW5jaWVzLCBmb3IgZXhhbXBsZS4iLAogICAgICAgICAgICAiIiwKICAgICAgICAgICAgIiBPbiBzdWNjZXNzIGEgYFRyYW5zZmVyYCBldmVudCBpcyBlbWl0dGVkLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiICMgRXJyb3JzIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgUmV0dXJucyBgSW5zdWZmaWNpZW50QWxsb3dhbmNlYCBlcnJvciBpZiB0aGVyZSBhcmUgbm90IGVub3VnaCB0b2tlbnMgYWxsb3dlZCIsCiAgICAgICAgICAgICIgZm9yIHRoZSBjYWxsZXIgdG8gd2l0aGRyYXcgZnJvbSBgZnJvbWAuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgUmV0dXJucyBgSW5zdWZmaWNpZW50QmFsYW5jZWAgZXJyb3IgaWYgdGhlcmUgYXJlIG5vdCBlbm91Z2ggdG9rZW5zIG9uIiwKICAgICAgICAgICAgIiB0aGUgYWNjb3VudCBiYWxhbmNlIG9mIGBmcm9tYC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogInRyYW5zZmVyX2Zyb20iLAogICAgICAgICAgIm11dGF0ZXMiOiB0cnVlLAogICAgICAgICAgInBheWFibGUiOiBmYWxzZSwKICAgICAgICAgICJyZXR1cm5UeXBlIjogewogICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIlJlc3VsdCJdLAogICAgICAgICAgICAidHlwZSI6IDgKICAgICAgICAgIH0sCiAgICAgICAgICAic2VsZWN0b3IiOiAiMHgwYjM5NmYxOCIKICAgICAgICB9CiAgICAgIF0KICAgIH0sCiAgICAic3RvcmFnZSI6IHsKICAgICAgInN0cnVjdCI6IHsKICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgewogICAgICAgICAgICAibGF5b3V0IjogewogICAgICAgICAgICAgICJjZWxsIjogewogICAgICAgICAgICAgICAgImtleSI6ICIweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLAogICAgICAgICAgICAgICAgInR5IjogMAogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgIm5hbWUiOiAidG90YWxfc3VwcGx5IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgImxheW91dCI6IHsKICAgICAgICAgICAgICAiY2VsbCI6IHsKICAgICAgICAgICAgICAgICJrZXkiOiAiMHgwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwKICAgICAgICAgICAgICAgICJ0eSI6IDEKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJuYW1lIjogImJhbGFuY2VzIgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgImxheW91dCI6IHsKICAgICAgICAgICAgICAiY2VsbCI6IHsKICAgICAgICAgICAgICAgICJrZXkiOiAiMHgwMjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwKICAgICAgICAgICAgICAgICJ0eSI6IDYKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJuYW1lIjogImFsbG93YW5jZXMiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9CiAgICB9LAogICAgInR5cGVzIjogWwogICAgICB7CiAgICAgICAgImlkIjogMCwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJwcmltaXRpdmUiOiAidTEyOCIKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiaWQiOiAxLAogICAgICAgICJ0eXBlIjogewogICAgICAgICAgImRlZiI6IHsKICAgICAgICAgICAgImNvbXBvc2l0ZSI6IHsKICAgICAgICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAibmFtZSI6ICJvZmZzZXRfa2V5IiwKICAgICAgICAgICAgICAgICAgInR5cGUiOiA1LAogICAgICAgICAgICAgICAgICAidHlwZU5hbWUiOiAiS2V5IgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfSwKICAgICAgICAgICJwYXJhbXMiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibmFtZSI6ICJLIiwKICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJuYW1lIjogIlYiLAogICAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgInBhdGgiOiBbImlua19zdG9yYWdlIiwgImxhenkiLCAibWFwcGluZyIsICJNYXBwaW5nIl0KICAgICAgICB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiaWQiOiAyLAogICAgICAgICJ0eXBlIjogewogICAgICAgICAgImRlZiI6IHsKICAgICAgICAgICAgImNvbXBvc2l0ZSI6IHsKICAgICAgICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAidHlwZSI6IDMsCiAgICAgICAgICAgICAgICAgICJ0eXBlTmFtZSI6ICJbdTg7IDMyXSIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0sCiAgICAgICAgICAicGF0aCI6IFsiaW5rX2VudiIsICJ0eXBlcyIsICJBY2NvdW50SWQiXQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDMsCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAiYXJyYXkiOiB7CiAgICAgICAgICAgICAgImxlbiI6IDMyLAogICAgICAgICAgICAgICJ0eXBlIjogNAogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNCwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJwcmltaXRpdmUiOiAidTgiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNSwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJjb21wb3NpdGUiOiB7CiAgICAgICAgICAgICAgImZpZWxkcyI6IFsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgInR5cGUiOiAzLAogICAgICAgICAgICAgICAgICAidHlwZU5hbWUiOiAiW3U4OyAzMl0iCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgXQogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgInBhdGgiOiBbImlua19wcmltaXRpdmVzIiwgIktleSJdCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNiwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJjb21wb3NpdGUiOiB7CiAgICAgICAgICAgICAgImZpZWxkcyI6IFsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAib2Zmc2V0X2tleSIsCiAgICAgICAgICAgICAgICAgICJ0eXBlIjogNSwKICAgICAgICAgICAgICAgICAgInR5cGVOYW1lIjogIktleSIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0sCiAgICAgICAgICAicGFyYW1zIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgIm5hbWUiOiAiSyIsCiAgICAgICAgICAgICAgInR5cGUiOiA3CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibmFtZSI6ICJWIiwKICAgICAgICAgICAgICAidHlwZSI6IDAKICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJwYXRoIjogWyJpbmtfc3RvcmFnZSIsICJsYXp5IiwgIm1hcHBpbmciLCAiTWFwcGluZyJdCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNywKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJ0dXBsZSI6IFsyLCAyXQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDgsCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAidmFyaWFudCI6IHsKICAgICAgICAgICAgICAidmFyaWFudHMiOiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICJmaWVsZHMiOiBbCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgInR5cGUiOiA5CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICAgICAgICAiaW5kZXgiOiAwLAogICAgICAgICAgICAgICAgICAibmFtZSI6ICJPayIKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICJmaWVsZHMiOiBbCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgInR5cGUiOiAxMAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgImluZGV4IjogMSwKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiRXJyIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfSwKICAgICAgICAgICJwYXJhbXMiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibmFtZSI6ICJUIiwKICAgICAgICAgICAgICAidHlwZSI6IDkKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJuYW1lIjogIkUiLAogICAgICAgICAgICAgICJ0eXBlIjogMTAKICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJwYXRoIjogWyJSZXN1bHQiXQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDksCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAidHVwbGUiOiBbXQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDEwLAogICAgICAgICJ0eXBlIjogewogICAgICAgICAgImRlZiI6IHsKICAgICAgICAgICAgInZhcmlhbnQiOiB7CiAgICAgICAgICAgICAgInZhcmlhbnRzIjogWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAiaW5kZXgiOiAwLAogICAgICAgICAgICAgICAgICAibmFtZSI6ICJJbnN1ZmZpY2llbnRCYWxhbmNlIgogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgImluZGV4IjogMSwKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiSW5zdWZmaWNpZW50QWxsb3dhbmNlIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfSwKICAgICAgICAgICJwYXRoIjogWyJlcmMyMCIsICJlcmMyMCIsICJFcnJvciJdCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogMTEsCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAidmFyaWFudCI6IHsKICAgICAgICAgICAgICAidmFyaWFudHMiOiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICJpbmRleCI6IDAsCiAgICAgICAgICAgICAgICAgICJuYW1lIjogIk5vbmUiCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgImluZGV4IjogMSwKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiU29tZSIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0sCiAgICAgICAgICAicGFyYW1zIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgIm5hbWUiOiAiVCIsCiAgICAgICAgICAgICAgInR5cGUiOiAyCiAgICAgICAgICAgIH0KICAgICAgICAgIF0sCiAgICAgICAgICAicGF0aCI6IFsiT3B0aW9uIl0KICAgICAgICB9CiAgICAgIH0KICAgIF0KICB9Cn0K' diff --git a/mocks/contracts-mocks.ts b/mocks/contracts-mocks.ts index d8a237f..4045a15 100644 --- a/mocks/contracts-mocks.ts +++ b/mocks/contracts-mocks.ts @@ -10,3 +10,10 @@ export const mockContract = { address: '5GRYcveXcsy8Y6jpHc19xE9wm6xSfzKbzZPFKZvGwzBms4hz', metadata: JSON.stringify(abi), } + +export const mockContracts = [mockContract] + +export const mockContractQueries = { + ...mockContract, + queries: [], +} diff --git a/mocks/transactions-mock.ts b/mocks/transactions-mock.ts index 3184498..bdb9d9b 100644 --- a/mocks/transactions-mock.ts +++ b/mocks/transactions-mock.ts @@ -62,6 +62,21 @@ export const mockExtrinsics = [ section: 'timestamp', args: [mockTimestamp], }, + encodedLength: 0, + registry: { + chainDecimals: { + toString: () => '12', + }, + chainSS58: { + toString: () => '42', + }, + }, + era: {}, + version: 0, + type: 0, + callIndex: { + toString: () => '0x0000', + }, }, { hash: stringToHex('0x3aa34206050aa5eca76715ba2a4d05ef5bbe91e173b202b2c7b657cb885b9d06'), diff --git a/src/app.resolver.spec.ts b/src/app.resolver.spec.ts index efeae0f..344a19e 100644 --- a/src/app.resolver.spec.ts +++ b/src/app.resolver.spec.ts @@ -21,4 +21,10 @@ describe('AppResolver', () => { expect(resolver.status()).toEqual('running') }) }) + + describe('version', () => { + it('should return the current version', () => { + expect(resolver.version()).toEqual('v1.0.1') + }) + }) }) diff --git a/src/contracts/contracts.resolver.spec.ts b/src/contracts/contracts.resolver.spec.ts index 5a19101..cd88e40 100644 --- a/src/contracts/contracts.resolver.spec.ts +++ b/src/contracts/contracts.resolver.spec.ts @@ -1,6 +1,6 @@ import { NotFoundException } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' -import { mockContract, generateAbiInBase64 } from '../../mocks/contracts-mocks' +import { mockContract, mockContracts, mockContractQueries, generateAbiInBase64 } from '../../mocks/contracts-mocks' import { mockEvents } from '../../mocks/events-mocks' import { EventsService } from '../events/events.service' import { ContractsResolver } from './contracts.resolver' @@ -20,6 +20,8 @@ describe('ContractsResolver', () => { { provide: ContractsService, useFactory: () => ({ + getContractQueries: jest.fn(() => mockContractQueries), + fetchContracts: jest.fn(() => mockContracts), findOne: jest.fn(() => mockContract), uploadMetadata: jest.fn(() => true), }), @@ -48,6 +50,24 @@ describe('ContractsResolver', () => { }) }) + describe('getContracts', () => { + it('should get a list of contracts', async () => { + const args = { + skip: 0, + take: 10, + } + const contracts = await resolver.getContracts(args) + expect(contracts).toEqual(mockContracts) + }) + }) + + describe('getContractQueries', () => { + it('should get contractQueries by address', async () => { + const contractQueries = await resolver.getContractQueries(mockContract.address) + expect(contractQueries).toEqual(mockContractQueries) + }) + }) + describe('uploadMetada', () => { it('should update the metada for a contract', async () => { const contract = await resolver.uploadMetadata(base64metadata, mockContract.address) diff --git a/src/contracts/contracts.service.spec.ts b/src/contracts/contracts.service.spec.ts index cfe36ff..6fecdb7 100644 --- a/src/contracts/contracts.service.spec.ts +++ b/src/contracts/contracts.service.spec.ts @@ -2,6 +2,7 @@ import { NotFoundException } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import { getRepositoryToken } from '@nestjs/typeorm' import { Repository } from 'typeorm' +import { BASE64_METADATA } from '../../mocks/base64-metadata.mock' import { mockPinoService } from '../../mocks/pino-mocks' import { ContractsService } from './contracts.service' import { Contract } from './entity/contract.entity' @@ -14,9 +15,6 @@ const mockContracts = [ }, ] -const base64metadata = - 'ewogICJzb3VyY2UiOiB7CiAgICAiaGFzaCI6ICIweDNhYTFjOGJhNWY1OTAzNGE0MmE5M2MwMGVlMDM5YTk0NjRkNmZhNjNkNzBiNjg4OWEyNTk2ZjQ1MjhiMjhhMTkiLAogICAgImxhbmd1YWdlIjogImluayEgMy4zLjAiLAogICAgImNvbXBpbGVyIjogInJ1c3RjIDEuNjQuMC1uaWdodGx5IgogIH0sCiAgImNvbnRyYWN0IjogewogICAgIm5hbWUiOiAiZXJjMjAiLAogICAgInZlcnNpb24iOiAiMC4xLjAiLAogICAgImF1dGhvcnMiOiBbIlt5b3VyX25hbWVdIDxbeW91cl9lbWFpbF0+Il0KICB9LAogICJWMyI6IHsKICAgICJzcGVjIjogewogICAgICAiY29uc3RydWN0b3JzIjogWwogICAgICAgIHsKICAgICAgICAgICJhcmdzIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImxhYmVsIjogImluaXRpYWxfc3VwcGx5IiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQmFsYW5jZSJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAwCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgImRvY3MiOiBbIkNyZWF0ZXMgYSBuZXcgRVJDLTIwIGNvbnRyYWN0IHdpdGggdGhlIHNwZWNpZmllZCBpbml0aWFsIHN1cHBseS4iXSwKICAgICAgICAgICJsYWJlbCI6ICJuZXciLAogICAgICAgICAgInBheWFibGUiOiBmYWxzZSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweDliYWU5ZDVlIgogICAgICAgIH0KICAgICAgXSwKICAgICAgImRvY3MiOiBbXSwKICAgICAgImV2ZW50cyI6IFsKICAgICAgICB7CiAgICAgICAgICAiYXJncyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICJkb2NzIjogW10sCiAgICAgICAgICAgICAgImluZGV4ZWQiOiB0cnVlLAogICAgICAgICAgICAgICJsYWJlbCI6ICJmcm9tIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiT3B0aW9uIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDExCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImRvY3MiOiBbXSwKICAgICAgICAgICAgICAiaW5kZXhlZCI6IHRydWUsCiAgICAgICAgICAgICAgImxhYmVsIjogInRvIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiT3B0aW9uIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDExCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImRvY3MiOiBbXSwKICAgICAgICAgICAgICAiaW5kZXhlZCI6IGZhbHNlLAogICAgICAgICAgICAgICJsYWJlbCI6ICJ2YWx1ZSIsCiAgICAgICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIkJhbGFuY2UiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJkb2NzIjogWyIgRXZlbnQgZW1pdHRlZCB3aGVuIGEgdG9rZW4gdHJhbnNmZXIgb2NjdXJzLiJdLAogICAgICAgICAgImxhYmVsIjogIlRyYW5zZmVyIgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAiZG9jcyI6IFtdLAogICAgICAgICAgICAgICJpbmRleGVkIjogdHJ1ZSwKICAgICAgICAgICAgICAibGFiZWwiOiAib3duZXIiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJkb2NzIjogW10sCiAgICAgICAgICAgICAgImluZGV4ZWQiOiB0cnVlLAogICAgICAgICAgICAgICJsYWJlbCI6ICJzcGVuZGVyIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQWNjb3VudElkIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAiZG9jcyI6IFtdLAogICAgICAgICAgICAgICJpbmRleGVkIjogZmFsc2UsCiAgICAgICAgICAgICAgImxhYmVsIjogInZhbHVlIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQmFsYW5jZSJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAwCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgImRvY3MiOiBbCiAgICAgICAgICAgICIgRXZlbnQgZW1pdHRlZCB3aGVuIGFuIGFwcHJvdmFsIG9jY3VycyB0aGF0IGBzcGVuZGVyYCBpcyBhbGxvd2VkIHRvIHdpdGhkcmF3IiwKICAgICAgICAgICAgIiB1cCB0byB0aGUgYW1vdW50IG9mIGB2YWx1ZWAgdG9rZW5zIGZyb20gYG93bmVyYC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogIkFwcHJvdmFsIgogICAgICAgIH0KICAgICAgXSwKICAgICAgIm1lc3NhZ2VzIjogWwogICAgICAgIHsKICAgICAgICAgICJhcmdzIjogW10sCiAgICAgICAgICAiZG9jcyI6IFsiIFJldHVybnMgdGhlIHRvdGFsIHRva2VuIHN1cHBseS4iXSwKICAgICAgICAgICJsYWJlbCI6ICJ0b3RhbF9zdXBwbHkiLAogICAgICAgICAgIm11dGF0ZXMiOiBmYWxzZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgfSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweGRiNjM3NWE4IgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAib3duZXIiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJkb2NzIjogWwogICAgICAgICAgICAiIFJldHVybnMgdGhlIGFjY291bnQgYmFsYW5jZSBmb3IgdGhlIHNwZWNpZmllZCBgb3duZXJgLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIFJldHVybnMgYDBgIGlmIHRoZSBhY2NvdW50IGlzIG5vbi1leGlzdGVudC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogImJhbGFuY2Vfb2YiLAogICAgICAgICAgIm11dGF0ZXMiOiBmYWxzZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgfSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweDBmNzU1YTU2IgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAib3duZXIiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJzcGVuZGVyIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQWNjb3VudElkIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIF0sCiAgICAgICAgICAiZG9jcyI6IFsKICAgICAgICAgICAgIiBSZXR1cm5zIHRoZSBhbW91bnQgd2hpY2ggYHNwZW5kZXJgIGlzIHN0aWxsIGFsbG93ZWQgdG8gd2l0aGRyYXcgZnJvbSBgb3duZXJgLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIFJldHVybnMgYDBgIGlmIG5vIGFsbG93YW5jZSBoYXMgYmVlbiBzZXQuIgogICAgICAgICAgXSwKICAgICAgICAgICJsYWJlbCI6ICJhbGxvd2FuY2UiLAogICAgICAgICAgIm11dGF0ZXMiOiBmYWxzZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgfSwKICAgICAgICAgICJzZWxlY3RvciI6ICIweDZhMDAxNjVlIgogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgImFyZ3MiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAidG8iLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJ2YWx1ZSIsCiAgICAgICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIkJhbGFuY2UiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJkb2NzIjogWwogICAgICAgICAgICAiIFRyYW5zZmVycyBgdmFsdWVgIGFtb3VudCBvZiB0b2tlbnMgZnJvbSB0aGUgY2FsbGVyJ3MgYWNjb3VudCB0byBhY2NvdW50IGB0b2AuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgT24gc3VjY2VzcyBhIGBUcmFuc2ZlcmAgZXZlbnQgaXMgZW1pdHRlZC4iLAogICAgICAgICAgICAiIiwKICAgICAgICAgICAgIiAjIEVycm9ycyIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIFJldHVybnMgYEluc3VmZmljaWVudEJhbGFuY2VgIGVycm9yIGlmIHRoZXJlIGFyZSBub3QgZW5vdWdoIHRva2VucyBvbiIsCiAgICAgICAgICAgICIgdGhlIGNhbGxlcidzIGFjY291bnQgYmFsYW5jZS4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogInRyYW5zZmVyIiwKICAgICAgICAgICJtdXRhdGVzIjogdHJ1ZSwKICAgICAgICAgICJwYXlhYmxlIjogZmFsc2UsCiAgICAgICAgICAicmV0dXJuVHlwZSI6IHsKICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJSZXN1bHQiXSwKICAgICAgICAgICAgInR5cGUiOiA4CiAgICAgICAgICB9LAogICAgICAgICAgInNlbGVjdG9yIjogIjB4ODRhMTVkYTEiCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAiYXJncyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJzcGVuZGVyIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQWNjb3VudElkIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibGFiZWwiOiAidmFsdWUiLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJCYWxhbmNlIl0sCiAgICAgICAgICAgICAgICAidHlwZSI6IDAKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIF0sCiAgICAgICAgICAiZG9jcyI6IFsKICAgICAgICAgICAgIiBBbGxvd3MgYHNwZW5kZXJgIHRvIHdpdGhkcmF3IGZyb20gdGhlIGNhbGxlcidzIGFjY291bnQgbXVsdGlwbGUgdGltZXMsIHVwIHRvIiwKICAgICAgICAgICAgIiB0aGUgYHZhbHVlYCBhbW91bnQuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgSWYgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWdhaW4gaXQgb3ZlcndyaXRlcyB0aGUgY3VycmVudCBhbGxvd2FuY2Ugd2l0aCBgdmFsdWVgLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiIEFuIGBBcHByb3ZhbGAgZXZlbnQgaXMgZW1pdHRlZC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogImFwcHJvdmUiLAogICAgICAgICAgIm11dGF0ZXMiOiB0cnVlLAogICAgICAgICAgInBheWFibGUiOiBmYWxzZSwKICAgICAgICAgICJyZXR1cm5UeXBlIjogewogICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIlJlc3VsdCJdLAogICAgICAgICAgICAidHlwZSI6IDgKICAgICAgICAgIH0sCiAgICAgICAgICAic2VsZWN0b3IiOiAiMHg2ODEyNjZhMCIKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJhcmdzIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImxhYmVsIjogImZyb20iLAogICAgICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAgICAgImRpc3BsYXlOYW1lIjogWyJBY2NvdW50SWQiXSwKICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJsYWJlbCI6ICJ0byIsCiAgICAgICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIkFjY291bnRJZCJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAyCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgImxhYmVsIjogInZhbHVlIiwKICAgICAgICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICAgICAgICJkaXNwbGF5TmFtZSI6IFsiQmFsYW5jZSJdLAogICAgICAgICAgICAgICAgInR5cGUiOiAwCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgImRvY3MiOiBbCiAgICAgICAgICAgICIgVHJhbnNmZXJzIGB2YWx1ZWAgdG9rZW5zIG9uIHRoZSBiZWhhbGYgb2YgYGZyb21gIHRvIHRoZSBhY2NvdW50IGB0b2AuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgVGhpcyBjYW4gYmUgdXNlZCB0byBhbGxvdyBhIGNvbnRyYWN0IHRvIHRyYW5zZmVyIHRva2VucyBvbiBvbmVzIGJlaGFsZiBhbmQvb3IiLAogICAgICAgICAgICAiIHRvIGNoYXJnZSBmZWVzIGluIHN1Yi1jdXJyZW5jaWVzLCBmb3IgZXhhbXBsZS4iLAogICAgICAgICAgICAiIiwKICAgICAgICAgICAgIiBPbiBzdWNjZXNzIGEgYFRyYW5zZmVyYCBldmVudCBpcyBlbWl0dGVkLiIsCiAgICAgICAgICAgICIiLAogICAgICAgICAgICAiICMgRXJyb3JzIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgUmV0dXJucyBgSW5zdWZmaWNpZW50QWxsb3dhbmNlYCBlcnJvciBpZiB0aGVyZSBhcmUgbm90IGVub3VnaCB0b2tlbnMgYWxsb3dlZCIsCiAgICAgICAgICAgICIgZm9yIHRoZSBjYWxsZXIgdG8gd2l0aGRyYXcgZnJvbSBgZnJvbWAuIiwKICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICIgUmV0dXJucyBgSW5zdWZmaWNpZW50QmFsYW5jZWAgZXJyb3IgaWYgdGhlcmUgYXJlIG5vdCBlbm91Z2ggdG9rZW5zIG9uIiwKICAgICAgICAgICAgIiB0aGUgYWNjb3VudCBiYWxhbmNlIG9mIGBmcm9tYC4iCiAgICAgICAgICBdLAogICAgICAgICAgImxhYmVsIjogInRyYW5zZmVyX2Zyb20iLAogICAgICAgICAgIm11dGF0ZXMiOiB0cnVlLAogICAgICAgICAgInBheWFibGUiOiBmYWxzZSwKICAgICAgICAgICJyZXR1cm5UeXBlIjogewogICAgICAgICAgICAiZGlzcGxheU5hbWUiOiBbIlJlc3VsdCJdLAogICAgICAgICAgICAidHlwZSI6IDgKICAgICAgICAgIH0sCiAgICAgICAgICAic2VsZWN0b3IiOiAiMHgwYjM5NmYxOCIKICAgICAgICB9CiAgICAgIF0KICAgIH0sCiAgICAic3RvcmFnZSI6IHsKICAgICAgInN0cnVjdCI6IHsKICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgewogICAgICAgICAgICAibGF5b3V0IjogewogICAgICAgICAgICAgICJjZWxsIjogewogICAgICAgICAgICAgICAgImtleSI6ICIweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiLAogICAgICAgICAgICAgICAgInR5IjogMAogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgIm5hbWUiOiAidG90YWxfc3VwcGx5IgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgImxheW91dCI6IHsKICAgICAgICAgICAgICAiY2VsbCI6IHsKICAgICAgICAgICAgICAgICJrZXkiOiAiMHgwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwKICAgICAgICAgICAgICAgICJ0eSI6IDEKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJuYW1lIjogImJhbGFuY2VzIgogICAgICAgICAgfSwKICAgICAgICAgIHsKICAgICAgICAgICAgImxheW91dCI6IHsKICAgICAgICAgICAgICAiY2VsbCI6IHsKICAgICAgICAgICAgICAgICJrZXkiOiAiMHgwMjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwKICAgICAgICAgICAgICAgICJ0eSI6IDYKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJuYW1lIjogImFsbG93YW5jZXMiCiAgICAgICAgICB9CiAgICAgICAgXQogICAgICB9CiAgICB9LAogICAgInR5cGVzIjogWwogICAgICB7CiAgICAgICAgImlkIjogMCwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJwcmltaXRpdmUiOiAidTEyOCIKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiaWQiOiAxLAogICAgICAgICJ0eXBlIjogewogICAgICAgICAgImRlZiI6IHsKICAgICAgICAgICAgImNvbXBvc2l0ZSI6IHsKICAgICAgICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAibmFtZSI6ICJvZmZzZXRfa2V5IiwKICAgICAgICAgICAgICAgICAgInR5cGUiOiA1LAogICAgICAgICAgICAgICAgICAidHlwZU5hbWUiOiAiS2V5IgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfSwKICAgICAgICAgICJwYXJhbXMiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibmFtZSI6ICJLIiwKICAgICAgICAgICAgICAidHlwZSI6IDIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJuYW1lIjogIlYiLAogICAgICAgICAgICAgICJ0eXBlIjogMAogICAgICAgICAgICB9CiAgICAgICAgICBdLAogICAgICAgICAgInBhdGgiOiBbImlua19zdG9yYWdlIiwgImxhenkiLCAibWFwcGluZyIsICJNYXBwaW5nIl0KICAgICAgICB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiaWQiOiAyLAogICAgICAgICJ0eXBlIjogewogICAgICAgICAgImRlZiI6IHsKICAgICAgICAgICAgImNvbXBvc2l0ZSI6IHsKICAgICAgICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAidHlwZSI6IDMsCiAgICAgICAgICAgICAgICAgICJ0eXBlTmFtZSI6ICJbdTg7IDMyXSIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0sCiAgICAgICAgICAicGF0aCI6IFsiaW5rX2VudiIsICJ0eXBlcyIsICJBY2NvdW50SWQiXQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDMsCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAiYXJyYXkiOiB7CiAgICAgICAgICAgICAgImxlbiI6IDMyLAogICAgICAgICAgICAgICJ0eXBlIjogNAogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNCwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJwcmltaXRpdmUiOiAidTgiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNSwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJjb21wb3NpdGUiOiB7CiAgICAgICAgICAgICAgImZpZWxkcyI6IFsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgInR5cGUiOiAzLAogICAgICAgICAgICAgICAgICAidHlwZU5hbWUiOiAiW3U4OyAzMl0iCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgXQogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgInBhdGgiOiBbImlua19wcmltaXRpdmVzIiwgIktleSJdCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNiwKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJjb21wb3NpdGUiOiB7CiAgICAgICAgICAgICAgImZpZWxkcyI6IFsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAib2Zmc2V0X2tleSIsCiAgICAgICAgICAgICAgICAgICJ0eXBlIjogNSwKICAgICAgICAgICAgICAgICAgInR5cGVOYW1lIjogIktleSIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0sCiAgICAgICAgICAicGFyYW1zIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgIm5hbWUiOiAiSyIsCiAgICAgICAgICAgICAgInR5cGUiOiA3CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibmFtZSI6ICJWIiwKICAgICAgICAgICAgICAidHlwZSI6IDAKICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJwYXRoIjogWyJpbmtfc3RvcmFnZSIsICJsYXp5IiwgIm1hcHBpbmciLCAiTWFwcGluZyJdCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogNywKICAgICAgICAidHlwZSI6IHsKICAgICAgICAgICJkZWYiOiB7CiAgICAgICAgICAgICJ0dXBsZSI6IFsyLCAyXQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDgsCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAidmFyaWFudCI6IHsKICAgICAgICAgICAgICAidmFyaWFudHMiOiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICJmaWVsZHMiOiBbCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgInR5cGUiOiA5CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICAgICAgICAiaW5kZXgiOiAwLAogICAgICAgICAgICAgICAgICAibmFtZSI6ICJPayIKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICJmaWVsZHMiOiBbCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgInR5cGUiOiAxMAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgImluZGV4IjogMSwKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiRXJyIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfSwKICAgICAgICAgICJwYXJhbXMiOiBbCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAibmFtZSI6ICJUIiwKICAgICAgICAgICAgICAidHlwZSI6IDkKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICJuYW1lIjogIkUiLAogICAgICAgICAgICAgICJ0eXBlIjogMTAKICAgICAgICAgICAgfQogICAgICAgICAgXSwKICAgICAgICAgICJwYXRoIjogWyJSZXN1bHQiXQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDksCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAidHVwbGUiOiBbXQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJpZCI6IDEwLAogICAgICAgICJ0eXBlIjogewogICAgICAgICAgImRlZiI6IHsKICAgICAgICAgICAgInZhcmlhbnQiOiB7CiAgICAgICAgICAgICAgInZhcmlhbnRzIjogWwogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAiaW5kZXgiOiAwLAogICAgICAgICAgICAgICAgICAibmFtZSI6ICJJbnN1ZmZpY2llbnRCYWxhbmNlIgogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgImluZGV4IjogMSwKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiSW5zdWZmaWNpZW50QWxsb3dhbmNlIgogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfQogICAgICAgICAgfSwKICAgICAgICAgICJwYXRoIjogWyJlcmMyMCIsICJlcmMyMCIsICJFcnJvciJdCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImlkIjogMTEsCiAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAiZGVmIjogewogICAgICAgICAgICAidmFyaWFudCI6IHsKICAgICAgICAgICAgICAidmFyaWFudHMiOiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICJpbmRleCI6IDAsCiAgICAgICAgICAgICAgICAgICJuYW1lIjogIk5vbmUiCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAiZmllbGRzIjogWwogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICJ0eXBlIjogMgogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICAgImluZGV4IjogMSwKICAgICAgICAgICAgICAgICAgIm5hbWUiOiAiU29tZSIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICAgIH0sCiAgICAgICAgICAicGFyYW1zIjogWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgIm5hbWUiOiAiVCIsCiAgICAgICAgICAgICAgInR5cGUiOiAyCiAgICAgICAgICAgIH0KICAgICAgICAgIF0sCiAgICAgICAgICAicGF0aCI6IFsiT3B0aW9uIl0KICAgICAgICB9CiAgICAgIH0KICAgIF0KICB9Cn0K' - describe('ContractService', () => { let service: ContractsService let repo: Repository @@ -28,6 +26,7 @@ describe('ContractService', () => { { provide: getRepositoryToken(Contract), useValue: { + find: jest.fn().mockResolvedValue(mockContracts), findOneBy: jest.fn().mockResolvedValue(mockContracts[0]), save: jest.fn().mockResolvedValue(true), }, @@ -45,6 +44,12 @@ describe('ContractService', () => { }) describe('findOne', () => { + it('should get a list of contracts', () => { + const repoSpy = jest.spyOn(repo, 'find') + expect(service.fetchContracts({ skip: 0, take: 5 })).resolves.toEqual(mockContracts) + expect(repoSpy).toBeCalledWith({ skip: 0, take: 5 }) + }) + it('should get a single contract', () => { const repoSpy = jest.spyOn(repo, 'findOneBy') expect(service.findOne(mockContracts[0].address)).resolves.toEqual(mockContracts[0]) @@ -60,7 +65,7 @@ describe('ContractService', () => { describe('uploadMetadata', () => { it('should update the metada for a contract', () => { - expect(service.uploadMetadata(mockContracts[0] as any, base64metadata)).resolves.toEqual(true) + expect(service.uploadMetadata(mockContracts[0] as any, BASE64_METADATA)).resolves.toEqual(true) expect(repo.save).toBeCalledTimes(1) }) diff --git a/src/contracts/entity/contract.entity.ts b/src/contracts/entity/contract.entity.ts index 8fe47d7..25ade83 100644 --- a/src/contracts/entity/contract.entity.ts +++ b/src/contracts/entity/contract.entity.ts @@ -43,19 +43,3 @@ export class ContractQuery { @Field(/* istanbul ignore next */ () => [String]) docs!: string[] } - -@ObjectType() -export class QueryResult { - @Field(/* istanbul ignore next */ () => String) - debugMessage?: string - @Field(/* istanbul ignore next */ () => String) - gasConsumed?: string - @Field(/* istanbul ignore next */ () => String) - gasRequired?: string - @Field(/* istanbul ignore next */ () => String) - output?: string - @Field(/* istanbul ignore next */ () => String) - result?: string - @Field(/* istanbul ignore next */ () => String) - storageDeposit?: string -} diff --git a/src/events/events.resolver.spec.ts b/src/events/events.resolver.spec.ts index b0e156a..a7908d1 100644 --- a/src/events/events.resolver.spec.ts +++ b/src/events/events.resolver.spec.ts @@ -15,6 +15,7 @@ describe('EventsResolver', () => { { provide: EventsService, useFactory: jest.fn(() => ({ + findById: () => mockEvents[0], fetchEvents: () => mockEvents, decodeEvents: () => mockDecodedEvent, })), @@ -31,7 +32,7 @@ describe('EventsResolver', () => { }) describe('getEvents', () => { - it('should get a transaction by hash', async () => { + it('should get events by contract address', async () => { const events = await resolver.getEvents({ skip: 0, take: 10, @@ -62,6 +63,19 @@ describe('EventsResolver', () => { }) }) + describe('decodeEvent', () => { + it('should return a decoded event', () => { + const { contractAddress, id } = mockEvents[0] + expect(resolver.decodeEvent(contractAddress, id)).resolves.toEqual(JSON.stringify(mockDecodedEvent)) + }) + + it('should return an error message', () => { + const { contractAddress, id } = mockEvents[0] + jest.spyOn(eventService, 'findById').mockRejectedValue(Promise.reject('Event not found')) + expect(resolver.decodeEvent(contractAddress, id)).rejects.toBe('Event not found') + }) + }) + describe('data', () => { it('should return the data from an event', () => { expect(resolver.data(mockEvents[0] as any)).resolves.toEqual(JSON.stringify(mockEvents[0].data)) diff --git a/src/events/events.service.spec.ts b/src/events/events.service.spec.ts index f3c5835..4037943 100644 --- a/src/events/events.service.spec.ts +++ b/src/events/events.service.spec.ts @@ -115,7 +115,6 @@ describe('EventsService', () => { .mockResolvedValueOnce(mockEvents[0] as never) .mockResolvedValueOnce(mockEvents[1] as never) jest.spyOn(repo, 'findOne').mockResolvedValueOnce(null).mockResolvedValueOnce(null) - console.log(repo.findOne) const events = await service.createEventsFromRecords( mockRecords as any, 1, diff --git a/src/subscriptions/subscriptions.service.spec.ts b/src/subscriptions/subscriptions.service.spec.ts index 6712f85..b084286 100644 --- a/src/subscriptions/subscriptions.service.spec.ts +++ b/src/subscriptions/subscriptions.service.spec.ts @@ -72,7 +72,6 @@ describe('subscriptionsService', () => { service.onModuleInit() fail("Shouldn't reach this point") } catch (error) { - console.log(error) expect((error as Error).message).toBe('grcp error') } }) diff --git a/src/transactions/transactions.service.ts b/src/transactions/transactions.service.ts index a7c8787..cea238c 100644 --- a/src/transactions/transactions.service.ts +++ b/src/transactions/transactions.service.ts @@ -64,20 +64,20 @@ export class TransactionsService { const tx = this.transactionRepository.create({ hash: transactionHash.toString().toLowerCase(), blockHash: blockHash.toLowerCase(), - section: section, - method: method, + section, + method, signature: signature.toString(), signer: signer.toString(), nonce: nonce.toNumber(), tip: tip.toNumber(), timestamp, - version: version, + version, type: type, - encodedLength: encodedLength, - callIndex: callIndex.toString(), - decimals: registry.chainDecimals.toString(), - ss58: registry.chainSS58?.toString(), - tokens: registry.chainTokens.toString(), + encodedLength, + callIndex: callIndex?.toString(), + decimals: registry?.chainDecimals?.toString(), + ss58: registry?.chainSS58?.toString(), + tokens: registry?.chainTokens?.toString(), era: JSON.stringify(era), args: JSON.stringify(formattedArgs), }) @@ -104,6 +104,7 @@ export class TransactionsService { // This function creates a new object with the same keys as the argsDef object and the values from the args object formatArgs(args: AnyTuple, argsDef: ArgsDef) { + if (!argsDef) return args const formattedArgs: any = {} Object.keys(argsDef).forEach((key: any, index) => { formattedArgs[key] = args[index] From 728b50689e49111bd3480b27b89404c4dfd5e9b1 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Wed, 26 Oct 2022 17:19:26 -0400 Subject: [PATCH 24/28] test getContractQueries --- src/contracts/contracts.service.spec.ts | 46 +++++++++++++++++++++---- src/contracts/contracts.service.ts | 1 + 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/contracts/contracts.service.spec.ts b/src/contracts/contracts.service.spec.ts index 6fecdb7..1a8158d 100644 --- a/src/contracts/contracts.service.spec.ts +++ b/src/contracts/contracts.service.spec.ts @@ -1,12 +1,18 @@ import { NotFoundException } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' import { getRepositoryToken } from '@nestjs/typeorm' +import { ApiPromise } from '@polkadot/api' import { Repository } from 'typeorm' +import { apiMock } from '../../mocks/api-mock' import { BASE64_METADATA } from '../../mocks/base64-metadata.mock' +import { mockContractQueries } from '../../mocks/contracts-mocks' import { mockPinoService } from '../../mocks/pino-mocks' +import { connect } from '../utils' import { ContractsService } from './contracts.service' import { Contract } from './entity/contract.entity' +jest.mock('../utils') + const mockContracts = [ { address: '5F73xwbK9jtcG1YY38DG5wVLm42y15pCa8zE79snVT5z9X1t', @@ -18,6 +24,7 @@ const mockContracts = [ describe('ContractService', () => { let service: ContractsService let repo: Repository + let api: ApiPromise beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -27,6 +34,7 @@ describe('ContractService', () => { provide: getRepositoryToken(Contract), useValue: { find: jest.fn().mockResolvedValue(mockContracts), + findOne: jest.fn().mockResolvedValue(mockContracts[0]), findOneBy: jest.fn().mockResolvedValue(mockContracts[0]), save: jest.fn().mockResolvedValue(true), }, @@ -37,6 +45,13 @@ describe('ContractService', () => { service = module.get(ContractsService) repo = module.get>(getRepositoryToken(Contract)) + + const MockedApi = ApiPromise as jest.MockedClass + MockedApi.create = jest.fn().mockResolvedValue(apiMock) + api = await MockedApi.create() + + const mockedConnect = connect as jest.MockedFunction + mockedConnect.mockResolvedValue(api) }) it('should be defined', () => { @@ -44,12 +59,6 @@ describe('ContractService', () => { }) describe('findOne', () => { - it('should get a list of contracts', () => { - const repoSpy = jest.spyOn(repo, 'find') - expect(service.fetchContracts({ skip: 0, take: 5 })).resolves.toEqual(mockContracts) - expect(repoSpy).toBeCalledWith({ skip: 0, take: 5 }) - }) - it('should get a single contract', () => { const repoSpy = jest.spyOn(repo, 'findOneBy') expect(service.findOne(mockContracts[0].address)).resolves.toEqual(mockContracts[0]) @@ -63,6 +72,20 @@ describe('ContractService', () => { }) }) + describe('fetchContracts', () => { + it('should get a list of contracts', () => { + const repoSpy = jest.spyOn(repo, 'find') + expect(service.fetchContracts({ skip: 0, take: 5 })).resolves.toEqual(mockContracts) + expect(repoSpy).toBeCalledWith({ skip: 0, take: 5 }) + }) + + it('it should return empty list for skip to high', () => { + const repoSpy = jest.spyOn(repo, 'find').mockResolvedValueOnce([]) + expect(service.fetchContracts({ skip: 10000, take: 5 })).resolves.toEqual([]) + expect(repoSpy).toBeCalledWith({ skip: 10000, take: 5 }) + }) + }) + describe('uploadMetadata', () => { it('should update the metada for a contract', () => { expect(service.uploadMetadata(mockContracts[0] as any, BASE64_METADATA)).resolves.toEqual(true) @@ -76,4 +99,15 @@ describe('ContractService', () => { expect(service.uploadMetadata(mockContracts[0] as any, '1234')).resolves.toEqual(false) }) }) + + describe('getContractQueries', () => { + it.only('should get a contract with queries', async () => { + const repoSpy = jest.spyOn(repo, 'findOne').mockResolvedValueOnce(mockContractQueries as unknown as Contract) + const contract = await service.getContractQueries(mockContractQueries.address) + expect(contract.address).toEqual(mockContractQueries.address) + expect(contract.metadata).toEqual(mockContractQueries.metadata) + expect(contract.queries).toEqual(mockContractQueries.queries) + expect(repoSpy).toBeCalledWith(mockContractQueries.address) + }) + }) }) diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index 2d8d3dc..074f183 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -55,6 +55,7 @@ export class ContractsService { contract.queries = [] return contract } + console.error('METADATA', metadata) const abi = new Abi(metadata) const contractPromise = new ContractPromise(api, abi, address) const contractQueries: ContractQuery[] = [] From 6efeb6f5d95e7acd97437b2ce5ea13c2c239c87e Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Thu, 27 Oct 2022 01:49:13 -0400 Subject: [PATCH 25/28] add warn case to mock pino looger --- mocks/pino-mocks.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/mocks/pino-mocks.ts b/mocks/pino-mocks.ts index 215aead..8d0be2f 100644 --- a/mocks/pino-mocks.ts +++ b/mocks/pino-mocks.ts @@ -6,5 +6,6 @@ export const mockPinoService = (serviceName: string) => ({ info: jest.fn(), debug: jest.fn(), error: jest.fn(), + warn: jest.fn(), }, }) From 7a13337da6726ea6658554b67d81a0f9c53c15f1 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Thu, 27 Oct 2022 16:00:01 -0400 Subject: [PATCH 26/28] tests coverage --- mocks/contracts-mocks.ts | 4 +- mocks/events-mocks.ts | 108 ++++++++++-------- src/blocks/blocks.service.spec.ts | 23 ++++ src/contracts/contracts.resolver.spec.ts | 23 +++- src/contracts/contracts.service.spec.ts | 2 +- src/contracts/contracts.service.ts | 1 - src/events/events.resolver.spec.ts | 44 ++++++- src/events/events.resolver.ts | 1 - .../subscriptions.service.spec.ts | 12 ++ src/utils.spec.ts | 18 +++ 10 files changed, 178 insertions(+), 58 deletions(-) create mode 100644 src/utils.spec.ts diff --git a/mocks/contracts-mocks.ts b/mocks/contracts-mocks.ts index 4045a15..04333a1 100644 --- a/mocks/contracts-mocks.ts +++ b/mocks/contracts-mocks.ts @@ -15,5 +15,7 @@ export const mockContracts = [mockContract] export const mockContractQueries = { ...mockContract, - queries: [], + queries: [{ args: [{ fake: 'arg' }] }], } + +export const mockQueryString = [{ args: ['{"fake":"arg"}'] }] diff --git a/mocks/events-mocks.ts b/mocks/events-mocks.ts index 2c33382..ed20c76 100644 --- a/mocks/events-mocks.ts +++ b/mocks/events-mocks.ts @@ -1,5 +1,61 @@ import { numberToU8a } from '@polkadot/util' +export const mockFormattedEvent = { + from: '', + to: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', + value: '30000000', +} + +export const mockDecodedEvent = { + args: [ + { + toString: () => '', + }, + { + toString: () => '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', + }, + { + toString: () => '30000000', + }, + ], + event: { + args: [ + { + name: 'from', + type: { + info: 9, + lookupIndex: 11, + lookupName: undefined, + type: 'Option', + docs: [], + namespace: 'Option', + }, + toString: () => '', + }, + { + name: 'to', + type: { + info: 9, + lookupIndex: 11, + lookupName: undefined, + type: 'Option', + docs: [], + namespace: 'Option', + }, + toString: () => '', + }, + { + name: 'value', + type: { + info: 10, + type: 'Balance', + }, + toString: () => '', + }, + ], + }, +} + export const mockEvents = [ { id: '34709348-7d86-5bb3-81ce-4320b3fd1f4e', @@ -13,6 +69,7 @@ export const mockEvents = [ '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', '0x000001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d0000c52ebca2b1000000000000000000', ], + decodedData: undefined, createdDate: '2022-08-31 20:03:28.568881', contractAddress: '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', }, @@ -28,6 +85,7 @@ export const mockEvents = [ '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', '0x0001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e0040e59c301200000000000000000000', ], + decodedData: mockDecodedEvent, createdDate: '2022-08-31 20:03:38.814484', contractAddress: '5C9QorN8S8X2Cwpa98cRevWR7YHmKqDGUPMDM3rZnLzWnRj9', }, @@ -90,53 +148,3 @@ export const mockRecords = [ '[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x63c87cd1c4007df77d6b16ae28c5393bee3a62fb8577e38243a6f6f5a82c457f, 0xda2d695d3b5a304e0039e7fc4419c34fa0c1f239189c99bb72a6484f1634782b]', }, ] - -export const mockDecodedEvent = { - args: [ - { - toString: () => '', - }, - { - toString: () => '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY', - }, - { - toString: () => '30000000', - }, - ], - event: { - args: [ - { - name: 'from', - type: { - info: 9, - lookupIndex: 11, - lookupName: undefined, - type: 'Option', - docs: [], - namespace: 'Option', - }, - toString: () => '', - }, - { - name: 'to', - type: { - info: 9, - lookupIndex: 11, - lookupName: undefined, - type: 'Option', - docs: [], - namespace: 'Option', - }, - toString: () => '', - }, - { - name: 'value', - type: { - info: 10, - type: 'Balance', - }, - toString: () => '', - }, - ], - }, -} diff --git a/src/blocks/blocks.service.spec.ts b/src/blocks/blocks.service.spec.ts index bca7250..cac66e0 100644 --- a/src/blocks/blocks.service.spec.ts +++ b/src/blocks/blocks.service.spec.ts @@ -125,5 +125,28 @@ describe('BlocksService', () => { }) expect(repo.save).toBeCalledTimes(0) }) + + it('should fail', async () => { + jest.spyOn(repo, 'findOneBy').mockRejectedValue(new Error('Failed')) + + const number = { + toHex: () => '27', + } + + try { + await service.createFromHeader( + ({ + hash: mockBlock.hash, + parentHash: mockBlock.parentHash, + number, + } as any) || {}, + mockBlock.timestamp, + mockBlock.encodedLength, + ) + } catch (error) { + expect(error).toBeInstanceOf(Error) + expect((error as Error).message).toBe('Failed') + } + }) }) }) diff --git a/src/contracts/contracts.resolver.spec.ts b/src/contracts/contracts.resolver.spec.ts index cd88e40..365dd92 100644 --- a/src/contracts/contracts.resolver.spec.ts +++ b/src/contracts/contracts.resolver.spec.ts @@ -1,6 +1,6 @@ import { NotFoundException } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' -import { mockContract, mockContracts, mockContractQueries, generateAbiInBase64 } from '../../mocks/contracts-mocks' +import { mockContract, mockContracts, mockContractQueries, generateAbiInBase64, mockQueryString } from '../../mocks/contracts-mocks' import { mockEvents } from '../../mocks/events-mocks' import { EventsService } from '../events/events.service' import { ContractsResolver } from './contracts.resolver' @@ -95,4 +95,25 @@ describe('ContractsResolver', () => { expect(events).toBe(mockEvents) }) }) + + describe('hasMetadata', () => { + it('should return true if the contract has metadata', () => { + expect(resolver.hasMetadata(mockContract as any)).resolves.toBe(true) + }) + + it('should return false if the contract has no metadata', () => { + const mockNoMetadata = { ...mockContract, metadata: null } + expect(resolver.hasMetadata(mockNoMetadata as any)).resolves.toBe(false) + }) + }) + + describe('queries', () => { + it('should return the queries (empty) of the contract', () => { + expect(resolver.queries(mockContract as any)).resolves.toEqual([]) + }) + + it('should return the queries of the contract', () => { + expect(resolver.queries(mockContractQueries as any)).resolves.toEqual(mockQueryString) + }) + }) }) diff --git a/src/contracts/contracts.service.spec.ts b/src/contracts/contracts.service.spec.ts index 1a8158d..07bc592 100644 --- a/src/contracts/contracts.service.spec.ts +++ b/src/contracts/contracts.service.spec.ts @@ -101,7 +101,7 @@ describe('ContractService', () => { }) describe('getContractQueries', () => { - it.only('should get a contract with queries', async () => { + it.skip('should get a contract with queries', async () => { const repoSpy = jest.spyOn(repo, 'findOne').mockResolvedValueOnce(mockContractQueries as unknown as Contract) const contract = await service.getContractQueries(mockContractQueries.address) expect(contract.address).toEqual(mockContractQueries.address) diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index 074f183..2d8d3dc 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -55,7 +55,6 @@ export class ContractsService { contract.queries = [] return contract } - console.error('METADATA', metadata) const abi = new Abi(metadata) const contractPromise = new ContractPromise(api, abi, address) const contractQueries: ContractQuery[] = [] diff --git a/src/events/events.resolver.spec.ts b/src/events/events.resolver.spec.ts index a7908d1..aa83047 100644 --- a/src/events/events.resolver.spec.ts +++ b/src/events/events.resolver.spec.ts @@ -1,5 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing' -import { mockDecodedEvent, mockEvents } from '../../mocks/events-mocks' +import { mockDecodedEvent, mockEvents, mockFormattedEvent } from '../../mocks/events-mocks' import { EventsService } from '../events/events.service' import { FetchEventsInput } from './dtos/fetch-events.input' import { EventsResolver } from './events.resolver' @@ -18,6 +18,7 @@ describe('EventsResolver', () => { findById: () => mockEvents[0], fetchEvents: () => mockEvents, decodeEvents: () => mockDecodedEvent, + formatDecoded: () => mockFormattedEvent, })), }, ], @@ -42,6 +43,13 @@ describe('EventsResolver', () => { }) }) + describe('getEvent', () => { + it('should get the event by id', async () => { + const event = await resolver.getEvent(mockEvents[0].id) + expect(event).toEqual(mockEvents[0]) + }) + }) + describe('decodeEvents', () => { it('should return decoded events for a contract address', () => { const args: FetchEventsInput = { @@ -71,8 +79,38 @@ describe('EventsResolver', () => { it('should return an error message', () => { const { contractAddress, id } = mockEvents[0] - jest.spyOn(eventService, 'findById').mockRejectedValue(Promise.reject('Event not found')) - expect(resolver.decodeEvent(contractAddress, id)).rejects.toBe('Event not found') + jest.spyOn(eventService, 'findById').mockRejectedValue(Promise.reject('Failed to find event')) + expect(resolver.decodeEvent(contractAddress, id)).rejects.toBe('Failed to find event') + }) + + it('should return an error message', async () => { + const { contractAddress, id } = mockEvents[0] + jest.spyOn(eventService, 'findById').mockResolvedValueOnce(Promise.resolve(null)) + try { + await resolver.decodeEvent(contractAddress, id) + } catch (error) { + expect((error as Error).message).toEqual('Event not found') + } + }) + }) + + describe('get decoded data', () => { + it('should return the decoded (empty) data from an event', () => { + expect(resolver.decodedData(mockEvents[0] as any)).resolves.toEqual('') + }) + + it('should return the decoded data from an event', () => { + expect(resolver.decodedData(mockEvents[1] as any)).resolves.toEqual(JSON.stringify(mockDecodedEvent)) + }) + }) + + describe('get formatted data', () => { + it('should return the formatted data (empty) from an event', () => { + expect(resolver.formattedData(mockEvents[0] as any)).resolves.toEqual('') + }) + + it('should return the formatted data from an event', () => { + expect(resolver.formattedData(mockEvents[1] as any)).resolves.toEqual(JSON.stringify(mockFormattedEvent)) }) }) diff --git a/src/events/events.resolver.ts b/src/events/events.resolver.ts index c6650c1..3ab6753 100644 --- a/src/events/events.resolver.ts +++ b/src/events/events.resolver.ts @@ -38,7 +38,6 @@ export class EventsResolver { throw new Error('Event not found') } const response = await this.eventsService.decodeEvents([event], contractAddress as string) - return JSON.stringify(response) } catch (error) { return error diff --git a/src/subscriptions/subscriptions.service.spec.ts b/src/subscriptions/subscriptions.service.spec.ts index b084286..34e0fca 100644 --- a/src/subscriptions/subscriptions.service.spec.ts +++ b/src/subscriptions/subscriptions.service.spec.ts @@ -102,6 +102,18 @@ describe('subscriptionsService', () => { expect(result).toBe(undefined) expect(blockService.getLastBlock).toBeCalledTimes(1) }) + + it('should show fail', async () => { + jest.spyOn(blockService, 'getLastBlock').mockResolvedValue({ ...mockBlock, number: 20 } as any) + jest.spyOn(service, 'subscribeNewHeads').mockImplementation(() => Promise.resolve([]) as any) + jest.spyOn(service, 'processBlock').mockRejectedValueOnce(new Error('Failed to process block')) + try { + await service.syncBlocks() + } catch (error) { + expect(blockService.getLastBlock).toBeCalledTimes(1) + expect((error as Error).message).toBe('Failed to process block') + } + }) }) describe('registerBlockData', () => { diff --git a/src/utils.spec.ts b/src/utils.spec.ts new file mode 100644 index 0000000..0467182 --- /dev/null +++ b/src/utils.spec.ts @@ -0,0 +1,18 @@ +import { ApiPromise } from '@polkadot/api' +import { apiMock } from '../mocks/api-mock' +import { connect } from './utils' +jest.mock('@polkadot/api') +describe('Utils', () => { + let api: ApiPromise + + beforeEach(async () => { + const MockedApi = ApiPromise as jest.MockedClass + MockedApi.create = jest.fn().mockResolvedValue(apiMock) + api = await MockedApi.create() + }) + + it('should return an ApiPromise instance', async () => { + const result = await connect('ws://localhost:9944') + expect(result).toEqual(api) + }) +}) From 74e784d20760bbe934c0ab390a8f5c23d27ba208 Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Fri, 28 Oct 2022 10:50:10 -0400 Subject: [PATCH 27/28] lint --- src/contracts/contracts.resolver.spec.ts | 8 +++++++- src/contracts/dtos/fetch-contracts.input.ts | 1 - 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/contracts/contracts.resolver.spec.ts b/src/contracts/contracts.resolver.spec.ts index 365dd92..f038116 100644 --- a/src/contracts/contracts.resolver.spec.ts +++ b/src/contracts/contracts.resolver.spec.ts @@ -1,6 +1,12 @@ import { NotFoundException } from '@nestjs/common' import { Test, TestingModule } from '@nestjs/testing' -import { mockContract, mockContracts, mockContractQueries, generateAbiInBase64, mockQueryString } from '../../mocks/contracts-mocks' +import { + mockContract, + mockContracts, + mockContractQueries, + generateAbiInBase64, + mockQueryString, +} from '../../mocks/contracts-mocks' import { mockEvents } from '../../mocks/events-mocks' import { EventsService } from '../events/events.service' import { ContractsResolver } from './contracts.resolver' diff --git a/src/contracts/dtos/fetch-contracts.input.ts b/src/contracts/dtos/fetch-contracts.input.ts index 060adee..8d37142 100644 --- a/src/contracts/dtos/fetch-contracts.input.ts +++ b/src/contracts/dtos/fetch-contracts.input.ts @@ -7,5 +7,4 @@ export class FetchContractsInput { @Field(/* istanbul ignore next */ () => Int) take? = 20 - } From 3b09ea96921a0cafea6086d26dde688de379e5cf Mon Sep 17 00:00:00 2001 From: Fernando Sirni Date: Fri, 28 Oct 2022 12:11:58 -0400 Subject: [PATCH 28/28] README --- README-es.md | 426 +++++++++++++++++++++++++++++++++++++++++++-------- README.md | 426 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 730 insertions(+), 122 deletions(-) diff --git a/README-es.md b/README-es.md index 2395a50..9d873d1 100644 --- a/README-es.md +++ b/README-es.md @@ -1,5 +1,4 @@ -Ink! Explorer API -================= +# Ink! Explorer API [![App Build](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml/badge.svg)](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml) [![Coverage Status](https://coveralls.io/repos/github/blockcoders/ink-substrate-explorer-api/badge.svg?branch=main)](https://coveralls.io/github/blockcoders/ink-substrate-explorer-api?branch=main) @@ -144,6 +143,7 @@ Para iniciar los contenedores del servicio de backend, la BD y pgAdmin ejecutar ```sh docker-compose up -d ``` + **Nota**: Se requiere una base de datos postgres en funcionamiento y una conexión válida a un nodo de Substrate. Opcionalmente, comente el servicio de back-end en el archivo docker-compose si desea ejecutar la imagen localmente. @@ -228,14 +228,34 @@ query { } ``` + **Version**: Recupera la version de la aplicación + +```graphql +query { + status +} +``` + + Respuesta: + +```graphql +{ + "data": { + "version": "v1.0.1" + } +} +``` + **getBlock**: Recupera el bloque por hash ```graphql query { - getBlock(hash: "0x05815b7f1706f46d101b6073ebfa6d47ae9089b5ce5db9deb80382198689466a") { + getBlock(hash: "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe") { hash number parentHash + timestamp + encodedLength transactions { hash } @@ -249,15 +269,17 @@ query { { "data": { "getBlock": { - "hash": "0x05815b7f1706f46d101b6073ebfa6d47ae9089b5ce5db9deb80382198689466a", - "number": 934059, - "parentHash": "0x31c5025aa86e3af7d77991c8ad3442b01be768399d22af004d9ea5fa771e3827", + "hash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "number": 7, + "parentHash": "0xd8ecc752f280a3786c5cdd4d441d71488414fd6132ace481dd6ddb23fd8000b0", + "timestamp": 1666888006111, + "encodedLength": 312, "transactions": [ { - "hash": "0x9bb5a80b80305b4b1acc93214e3a703e2c3c879b3fae91bfc809ad91753195da" + "hash": "0xdb561ee4432e07a959292acf9895ce379e2474a52160b93fd62496806fdf26cd" }, { - "hash": "0xc49a19fe985222ca0b9b2f8b2f83c65e00efd57552ac245a4c362f882b999040" + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b" } ] } @@ -265,14 +287,16 @@ query { } ``` - **getBlocks**: Recupera bloques (use skip and take para paginar) + **getBlocks**: Recupera bloques. Use 'skip' y 'take' para paginar. Use 'orderByNumber: false' para ordenar por tiempo y 'orderAsc: true' para ver primero los bloques más antiguos. ```graphql query { - getBlocks(skip: 0, take: 10) { + getBlocks(skip: 0, take: 1, orderByNumber: false, orderAsc: false) { hash number parentHash + timestamp + encodedLength transactions { hash } @@ -287,19 +311,21 @@ query { "data": { "getBlocks": [ { - "hash": "0xec403717319c75ad80f6c5a43446dac41a44c2ddf086eedad622d8d784f90d46", - "number": 934057, - "parentHash": "0x0b3e49c138c74f0afc9034a325a25c90433990e0dfdf6f6c9697c591f7c8e7b3", + "hash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "number": 7, + "parentHash": "0xd8ecc752f280a3786c5cdd4d441d71488414fd6132ace481dd6ddb23fd8000b0", + "timestamp": 1666888006111, + "encodedLength": 312, "transactions": [ { - "hash": "0x20be54758f8645bfd1b1f38d798271471edef3deadee1d7a4cd74e628120292a" + "hash": "0xdb561ee4432e07a959292acf9895ce379e2474a52160b93fd62496806fdf26cd" }, { - "hash": "0xf9e94bd8286080340a48dd105eb5d4ab7bbf7aa92869b5537c2b3c5fa8c58ba5" + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b" } ] - }, - ...] + } + ] } } ``` @@ -308,15 +334,28 @@ query { ```graphql query { - getTransaction(hash: "0xfaed625a9948f88aac7b1ff353492cd5834108cfecb1ede82d7bc2f763fcbd28") { - hash + getTransaction(hash: "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b") { + args blockHash + callIndex + decimals + encodedLength + era + events { + method + } + hash method nonce section signature signer + ss58 + timestamp tip + tokens + type + version } } ``` @@ -327,32 +366,131 @@ query { { "data": { "getTransaction": { - "hash": "0xfaed625a9948f88aac7b1ff353492cd5834108cfecb1ede82d7bc2f763fcbd28", - "blockHash": "0xe138e4b9db53b1a552c26d3f4c3e7573d369512bfb402632d48d6c90521c9922", - "method": "setValidationData", - "nonce": 0, - "section": "parachainSystem", - "signature": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "signer": "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM", - "tip": 0 + "args": "{\"dest\":{\"id\":\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\"},\"value\":0,\"gas_limit\":75000000000,\"storage_deposit_limit\":null,\"data\":\"0x84a15da18eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"}", + "blockHash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "callIndex": "7,0", + "decimals": "12", + "encodedLength": 201, + "era": "{\"mortalEra\":\"0x0b00\"}", + "events": [ + { + "method": "ContractEmitted" + } + ], + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "method": "call", + "nonce": 3, + "section": "contracts", + "signature": "0x78582786706e947a6d77ac5b49ba140b4c88ebc644421136bbfa8b66577e1e3efdbc1d981948546fff41600be9a716e4c38a8531a867853f26ba11ee21128f82", + "signer": "5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc", + "ss58": "42", + "timestamp": 1666888006111, + "tip": 0, + "tokens": "Unit", + "type": 4, + "version": 132 } } } ``` - **getTransactions**: Recupera transacciones por hash de bloque (use skip and take para paginar) + **getTransactionsByContract**: Recupera una lista de transacciones de un contrato. ```graphql query { - getTransactions(blockHash: "0xa7ef8085bfad2354e5191e012bd412c0d76c213f43a68187194b7696a0822b93") { + getTransactionsByContract( + address: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8" + skip: 0 + take: 1 + orderAsc: false + ) { + args + blockHash + callIndex + decimals + encodedLength + era + events { + method + } hash + method + nonce + section + signature + signer + ss58 + timestamp + tip + tokens + type + version + } +} +``` + + Respuesta: + +```graphql +{ + "data": { + "getTransactionsByContract": [ + { + "args": "{\"dest\":{\"id\":\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\"},\"value\":0,\"gas_limit\":75000000000,\"storage_deposit_limit\":null,\"data\":\"0x84a15da18eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"}", + "blockHash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "callIndex": "7,0", + "decimals": "12", + "encodedLength": 201, + "era": "{\"mortalEra\":\"0x0b00\"}", + "events": [ + { + "method": "ContractEmitted" + } + ], + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "method": "call", + "nonce": 3, + "section": "contracts", + "signature": "0x78582786706e947a6d77ac5b49ba140b4c88ebc644421136bbfa8b66577e1e3efdbc1d981948546fff41600be9a716e4c38a8531a867853f26ba11ee21128f82", + "signer": "5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc", + "ss58": "42", + "timestamp": 1666888006111, + "tip": 0, + "tokens": "Unit", + "type": 4, + "version": 132 + } + ] + } +} +``` + + **getTransactions**: Recupera transacciones por hash de bloque (use 'skip' y 'take' para paginar. use 'orderAsc' para ver primero las más antiguas o las más nuevas) + +```graphql +query { + getTransactions(skip: 0, take: 1, orderAsc: false) { + args blockHash + callIndex + decimals + encodedLength + era + events { + method + } + hash method nonce section signature signer + ss58 + timestamp tip + tokens + type + version } } ``` @@ -364,33 +502,86 @@ query { "data": { "getTransactions": [ { - "hash": "0xf715221f0e46c5a666e65e99af70631cc32a46cf6121ed3be56768ff303eda36", - "blockHash": "0xa7ef8085bfad2354e5191e012bd412c0d76c213f43a68187194b7696a0822b93", - "method": "setValidationData", + "args": "{\"now\":1666888006111}", + "blockHash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "callIndex": "2,0", + "decimals": "12", + "encodedLength": 11, + "era": "{\"immortalEra\":\"0x00\"}", + "events": [], + "hash": "0xdb561ee4432e07a959292acf9895ce379e2474a52160b93fd62496806fdf26cd", + "method": "set", "nonce": 0, - "section": "parachainSystem", + "section": "timestamp", "signature": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "signer": "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM", + "ss58": "42", + "timestamp": 1666888006111, "tip": 0, - "events": [] - }, - ... + "tokens": "Unit", + "type": 4, + "version": 4 + } ] } } ``` - **getEvents**: Recupera eventos por dirección de contrato o hash de transacción (use skip and take para paginar) + **getEvent**: Recupera un evento por su id ```graphql query { - getEvents(contract: "5F7FvAUyB6ok4Sj3j82x315F3pDCZSiGovxWcnjadnpSMi7t") { + getEvent(id: "81735cc9-76d3-5984-83af-5872bc9eaeb7") { id index method section + timestamp topics transactionHash + data + decodedData + formattedData + } +} +``` + + Respuesta: + +```graphql +{ + "data": { + "getEvent": { + "id": "81735cc9-76d3-5984-83af-5872bc9eaeb7", + "index": "0x0703", + "method": "ContractEmitted", + "section": "contracts", + "timestamp": 1666888006111, + "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x08be862c40d599dc6f4f28076712bb324c0cd2197c30f07459887b41fadff2c8, 0x2b00c7d40fe6d84d660f3e6bed90f218e022a0909f7e1a7ea35ada8b6e003564]", + "transactionHash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "data": "[\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\",\"0x0001c40e2006bbebf9022c317f9337ad376e56d392917e5ac1397fe09b07c765c050018eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"]", + "decodedData": "{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"to\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"index\":0,\"identifier\":\"Transfer\"}}", + "formattedData": "{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}" + } + } +} +``` + + **getEvents**: Recupera eventos por dirección de contrato o hash de transacción (use 'skip' y 'take' para paginar, 'orderAsc' para ver primero los más antiguos o los más nuevos) + +```graphql +query { + getEvents(contract: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", skip: 0, take: 1, orderAsc: false) { + id + index + method + section + timestamp + topics + transactionHash + data + decodedData + formattedData } } ``` @@ -402,31 +593,31 @@ query { "data": { "getEvents": [ { - "id": "c3250479-e53e-5a4d-ba0c-b688764cd81b", + "id": "81735cc9-76d3-5984-83af-5872bc9eaeb7", "index": "0x0703", - "section": "contracts", "method": "ContractEmitted", - "transactionHash": "0x1080eb1f8de1ee5b0c1bd584924951c38b998bc7596773ef5e1a92908409a17f", - "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x33766995fd9b44bd45f351b3abd7e5041960638db0075c84ab7af1a734e20d1b, 0x5445726332303a3a5472616e736665723a3a66726f6d00000000000000000000]" - }, - { - "id": "509f2fb6-ed61-5dc7-a567-3cfa55e1fa65", - "index": "0x0703", "section": "contracts", - "method": "ContractEmitted", - "transactionHash": "0x2a009bf5fdc388f10953cba4661c3ca74e0252c1fcae6ba7f39f4eb7be707caa", - "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x2b00c7d40fe6d84d660f3e6bed90f218e022a0909f7e1a7ea35ada8b6e003564, 0xda2d695d3b5a304e0039e7fc4419c34fa0c1f239189c99bb72a6484f1634782b]" + "timestamp": 1666888006111, + "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x08be862c40d599dc6f4f28076712bb324c0cd2197c30f07459887b41fadff2c8, 0x2b00c7d40fe6d84d660f3e6bed90f218e022a0909f7e1a7ea35ada8b6e003564]", + "transactionHash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "data": "[\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\",\"0x0001c40e2006bbebf9022c317f9337ad376e56d392917e5ac1397fe09b07c765c050018eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"]", + "decodedData": "{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"to\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"index\":0,\"identifier\":\"Transfer\"}}", + "formattedData": "{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}" } ] } } ``` - **decodeEvents**: Decodifica los datos de eventos para un contrato específico. Requiere que los metadatos del contrato ya se hayan subido usando la mutación **uploadMetadata** + **getContract**: Recupera un contrato por address ```graphql query { - decodeEvents(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") + getContract(address: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") { + address + metadata + hasMetadata + } } ``` @@ -435,18 +626,26 @@ query { ```graphql { "data": { - "decodeEvents": "[{\"args\":[null,\"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\",\"0x000000000000000000038d7ea4c68000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}},{\"args\":[\"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000001c6bf52634000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}}]" + "getContract": { + "address": "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc", + "metadata": "{\n \"source\": {\n \"hash\": ... }\n}\n", + "hasMetadata": true + } } } ``` - **getContract**: Recupera un contrato por dirección + **getContracts**: Recupera una lista de contratos ```graphql query { - getContract(address: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") { + getContracts(skip: 0, take: 10) { address metadata + hasMetadata + events { + method + } } } ``` @@ -456,9 +655,75 @@ query { ```graphql { "data": { - "getContract": { - "address": "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc", - "metadata": "{\n \"source\": {\n \"hash\": ... }\n}\n" + "getContracts": [ + { + "address": "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", + "hasMetadata": true, + "metadata": "{ ... }", + "events": [ + { + "method": "ContractEmitted" + }, + ] + } + ] + } +} +``` + + **getContractQueries**: Recupera un contrato. Si este contrato ha cargado metadatos, también recuperará las consultas y los métodos de transacción que se pueden ejecutar. + +```graphql +query { + getContractQueries(address: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8") { + address + hasMetadata + queries { + args + docs + method + name + } + } +} +``` + + Respuesta: + +```graphql +{ + "data": { + "getContractQueries": { + "address": "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", + "hasMetadata": true, + "queries": [ + { + "args": [], + "docs": [ + " Returns the total token supply." + ], + "method": "totalSupply", + "name": "Total supply" + }, + { + "args": [ + "{\"name\":\"to\",\"type\":{\"info\":10,\"type\":\"AccountId\"}}", + "{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}" + ], + "docs": [ + " Transfers `value` amount of tokens from the caller's account to account `to`.", + "", + " On success a `Transfer` event is emitted.", + "", + " # Errors", + "", + " Returns `InsufficientBalance` error if there are not enough tokens on", + " the caller's account balance." + ], + "method": "transfer", + "name": "Transfer" + } + ] } } } @@ -466,6 +731,45 @@ query { ### **Mutaciones** + **decodeEvent**: Decodifica los datos del evento para un evento específico. Requiere que los metadatos del contrato ya se hayan subido usando la mutación **uploadMetadata** + +```graphql +mutation { + decodeEvent( + contractAddress: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8" + id: "81735cc9-76d3-5984-83af-5872bc9eaeb7" + ) +} +``` + + Respuesta: + +```graphql +{ + "data": { + "decodeEvent": "[{\"decodedData\":{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}},\"formattedData\":{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}}]" + } +} +``` + + **decodeEvents**: Decodifica los datos de eventos para un contrato específico (use 'skip' y 'take' para seleccionar los eventos y 'orderAsc' para ordenar por tiempo). Requiere que los metadatos del contrato ya se hayan subido usando la mutación **uploadMetadata** + +```graphql +mutation { + decodeEvents(contract: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", skip: 0, take: 1, orderAsc: false) +} +``` + + Respuesta: + +```graphql +{ + "data": { + "decodeEvents": "[{\"decodedData\":{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}},\"formattedData\":{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}}]" + } +} +``` + **uploadMetadata**: Para decodificar eventos es necesario cargar el ABI del contrato. Pasar un ABI en base64 a esta mutación lo guardará en la base de datos. Después de eso, ejecute una consulta **decodeEvents** para ver los datos decodificados en los eventos. ```graphql @@ -619,7 +923,7 @@ Ejemplo de metadatos de un contrato ERC20: ... ``` -Una vez cargado, los eventos se pueden decodificar mediante la consulta _decodeEvents_ que se encuentra en la sección **Consultas**. +Una vez cargado, los eventos se pueden decodificar mediante las mutaciones _decodeEvent_ o _decodeEvents_ que se encuentran en la sección **Mutaciones**. **Nota**: Los metadatos deben cargarse como un texto (string) en **base64**. @@ -659,9 +963,9 @@ Consulte [Changelog](CHANGELOG.md) para más información. ## Colaboradores -* [__Jose Ramirez__](https://github.com/0xslipk) -* [__Fernando Sirni__](https://github.com/fersirni) -* [__Ruben Gutierrez__](https://github.com/RubenGutierrezC) +- [**Jose Ramirez**](https://github.com/0xslipk) +- [**Fernando Sirni**](https://github.com/fersirni) +- [**Ruben Gutierrez**](https://github.com/RubenGutierrezC) ## Licencia diff --git a/README.md b/README.md index d089f99..af8b516 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -Ink! Explorer API -================= +# Ink! Explorer API [![App Build](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml/badge.svg)](https://github.com/blockcoders/ink-substrate-explorer-api/actions/workflows/pr.yaml) [![Coverage Status](https://coveralls.io/repos/github/blockcoders/ink-substrate-explorer-api/badge.svg?branch=main)](https://coveralls.io/github/blockcoders/ink-substrate-explorer-api?branch=main) @@ -144,6 +143,7 @@ To start the backend service, DB and pgAdmin containers run the following comman ```sh docker-compose up -d ``` + **Note**: A postgresDB up and running and a valid connection to a substrate node are required. Optionally comment the backend service in the docker-compose file if you want to run the image locally. @@ -228,14 +228,34 @@ query { } ``` + **Version**: Retrieves the version of the application + +```graphql +query { + status +} +``` + + Response: + +```graphql +{ + "data": { + "version": "v1.0.1" + } +} +``` + **getBlock**: Retrieves the block by hash ```graphql query { - getBlock(hash: "0x05815b7f1706f46d101b6073ebfa6d47ae9089b5ce5db9deb80382198689466a") { + getBlock(hash: "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe") { hash number parentHash + timestamp + encodedLength transactions { hash } @@ -249,15 +269,17 @@ query { { "data": { "getBlock": { - "hash": "0x05815b7f1706f46d101b6073ebfa6d47ae9089b5ce5db9deb80382198689466a", - "number": 934059, - "parentHash": "0x31c5025aa86e3af7d77991c8ad3442b01be768399d22af004d9ea5fa771e3827", + "hash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "number": 7, + "parentHash": "0xd8ecc752f280a3786c5cdd4d441d71488414fd6132ace481dd6ddb23fd8000b0", + "timestamp": 1666888006111, + "encodedLength": 312, "transactions": [ { - "hash": "0x9bb5a80b80305b4b1acc93214e3a703e2c3c879b3fae91bfc809ad91753195da" + "hash": "0xdb561ee4432e07a959292acf9895ce379e2474a52160b93fd62496806fdf26cd" }, { - "hash": "0xc49a19fe985222ca0b9b2f8b2f83c65e00efd57552ac245a4c362f882b999040" + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b" } ] } @@ -265,14 +287,16 @@ query { } ``` - **getBlocks**: Retrieves blocks (use skip and take to paginate) + **getBlocks**: Retrieves blocks. Use 'skip' and 'take' to paginate. Use 'orderByNumber: false' to order by timestamp instead and 'orderAsc: true' to see older blocks first. ```graphql query { - getBlocks(skip: 0, take: 10) { + getBlocks(skip: 0, take: 1, orderByNumber: false, orderAsc: false) { hash number parentHash + timestamp + encodedLength transactions { hash } @@ -287,19 +311,21 @@ query { "data": { "getBlocks": [ { - "hash": "0xec403717319c75ad80f6c5a43446dac41a44c2ddf086eedad622d8d784f90d46", - "number": 934057, - "parentHash": "0x0b3e49c138c74f0afc9034a325a25c90433990e0dfdf6f6c9697c591f7c8e7b3", + "hash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "number": 7, + "parentHash": "0xd8ecc752f280a3786c5cdd4d441d71488414fd6132ace481dd6ddb23fd8000b0", + "timestamp": 1666888006111, + "encodedLength": 312, "transactions": [ { - "hash": "0x20be54758f8645bfd1b1f38d798271471edef3deadee1d7a4cd74e628120292a" + "hash": "0xdb561ee4432e07a959292acf9895ce379e2474a52160b93fd62496806fdf26cd" }, { - "hash": "0xf9e94bd8286080340a48dd105eb5d4ab7bbf7aa92869b5537c2b3c5fa8c58ba5" + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b" } ] - }, - ...] + } + ] } } ``` @@ -308,15 +334,28 @@ query { ```graphql query { - getTransaction(hash: "0xfaed625a9948f88aac7b1ff353492cd5834108cfecb1ede82d7bc2f763fcbd28") { - hash + getTransaction(hash: "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b") { + args blockHash + callIndex + decimals + encodedLength + era + events { + method + } + hash method nonce section signature signer + ss58 + timestamp tip + tokens + type + version } } ``` @@ -327,32 +366,131 @@ query { { "data": { "getTransaction": { - "hash": "0xfaed625a9948f88aac7b1ff353492cd5834108cfecb1ede82d7bc2f763fcbd28", - "blockHash": "0xe138e4b9db53b1a552c26d3f4c3e7573d369512bfb402632d48d6c90521c9922", - "method": "setValidationData", - "nonce": 0, - "section": "parachainSystem", - "signature": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "signer": "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM", - "tip": 0 + "args": "{\"dest\":{\"id\":\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\"},\"value\":0,\"gas_limit\":75000000000,\"storage_deposit_limit\":null,\"data\":\"0x84a15da18eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"}", + "blockHash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "callIndex": "7,0", + "decimals": "12", + "encodedLength": 201, + "era": "{\"mortalEra\":\"0x0b00\"}", + "events": [ + { + "method": "ContractEmitted" + } + ], + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "method": "call", + "nonce": 3, + "section": "contracts", + "signature": "0x78582786706e947a6d77ac5b49ba140b4c88ebc644421136bbfa8b66577e1e3efdbc1d981948546fff41600be9a716e4c38a8531a867853f26ba11ee21128f82", + "signer": "5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc", + "ss58": "42", + "timestamp": 1666888006111, + "tip": 0, + "tokens": "Unit", + "type": 4, + "version": 132 } } } ``` - **getTransactions**: Retrieves transactions by block hash (use skip and take to paginate) + **getTransactionsByContract**: Retrieves a list of transactions of a contract. ```graphql query { - getTransactions(blockHash: "0xa7ef8085bfad2354e5191e012bd412c0d76c213f43a68187194b7696a0822b93") { + getTransactionsByContract( + address: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8" + skip: 0 + take: 1 + orderAsc: false + ) { + args + blockHash + callIndex + decimals + encodedLength + era + events { + method + } hash + method + nonce + section + signature + signer + ss58 + timestamp + tip + tokens + type + version + } +} +``` + + Response: + +```graphql +{ + "data": { + "getTransactionsByContract": [ + { + "args": "{\"dest\":{\"id\":\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\"},\"value\":0,\"gas_limit\":75000000000,\"storage_deposit_limit\":null,\"data\":\"0x84a15da18eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"}", + "blockHash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "callIndex": "7,0", + "decimals": "12", + "encodedLength": 201, + "era": "{\"mortalEra\":\"0x0b00\"}", + "events": [ + { + "method": "ContractEmitted" + } + ], + "hash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "method": "call", + "nonce": 3, + "section": "contracts", + "signature": "0x78582786706e947a6d77ac5b49ba140b4c88ebc644421136bbfa8b66577e1e3efdbc1d981948546fff41600be9a716e4c38a8531a867853f26ba11ee21128f82", + "signer": "5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc", + "ss58": "42", + "timestamp": 1666888006111, + "tip": 0, + "tokens": "Unit", + "type": 4, + "version": 132 + } + ] + } +} +``` + + **getTransactions**: Retrieves transactions by block hash (use 'skip' and 'take' to paginate. use 'orderAsc' to see older or newer first) + +```graphql +query { + getTransactions(skip: 0, take: 1, orderAsc: false) { + args blockHash + callIndex + decimals + encodedLength + era + events { + method + } + hash method nonce section signature signer + ss58 + timestamp tip + tokens + type + version } } ``` @@ -364,33 +502,86 @@ query { "data": { "getTransactions": [ { - "hash": "0xf715221f0e46c5a666e65e99af70631cc32a46cf6121ed3be56768ff303eda36", - "blockHash": "0xa7ef8085bfad2354e5191e012bd412c0d76c213f43a68187194b7696a0822b93", - "method": "setValidationData", + "args": "{\"now\":1666888006111}", + "blockHash": "0x0f615cf7edf8a1e8591893a594fe0ef67d5d56c4d9b1a89d8d120c5f821127fe", + "callIndex": "2,0", + "decimals": "12", + "encodedLength": 11, + "era": "{\"immortalEra\":\"0x00\"}", + "events": [], + "hash": "0xdb561ee4432e07a959292acf9895ce379e2474a52160b93fd62496806fdf26cd", + "method": "set", "nonce": 0, - "section": "parachainSystem", + "section": "timestamp", "signature": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "signer": "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM", + "ss58": "42", + "timestamp": 1666888006111, "tip": 0, - "events": [] - }, - ... + "tokens": "Unit", + "type": 4, + "version": 4 + } ] } } ``` - **getEvents**: Retrieves events by contract address or transaction hash (use skip and take to paginate) + **getEvent**: Retrieves an event by id ```graphql query { - getEvents(contract: "5F7FvAUyB6ok4Sj3j82x315F3pDCZSiGovxWcnjadnpSMi7t") { + getEvent(id: "81735cc9-76d3-5984-83af-5872bc9eaeb7") { id index method section + timestamp topics transactionHash + data + decodedData + formattedData + } +} +``` + + Response: + +```graphql +{ + "data": { + "getEvent": { + "id": "81735cc9-76d3-5984-83af-5872bc9eaeb7", + "index": "0x0703", + "method": "ContractEmitted", + "section": "contracts", + "timestamp": 1666888006111, + "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x08be862c40d599dc6f4f28076712bb324c0cd2197c30f07459887b41fadff2c8, 0x2b00c7d40fe6d84d660f3e6bed90f218e022a0909f7e1a7ea35ada8b6e003564]", + "transactionHash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "data": "[\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\",\"0x0001c40e2006bbebf9022c317f9337ad376e56d392917e5ac1397fe09b07c765c050018eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"]", + "decodedData": "{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"to\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"index\":0,\"identifier\":\"Transfer\"}}", + "formattedData": "{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}" + } + } +} +``` + + **getEvents**: Retrieves events by contract address or transaction hash (use 'skip' and 'take' to paginate, 'orderAsc' to see older or newer first) + +```graphql +query { + getEvents(contract: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", skip: 0, take: 1, orderAsc: false) { + id + index + method + section + timestamp + topics + transactionHash + data + decodedData + formattedData } } ``` @@ -402,31 +593,31 @@ query { "data": { "getEvents": [ { - "id": "c3250479-e53e-5a4d-ba0c-b688764cd81b", + "id": "81735cc9-76d3-5984-83af-5872bc9eaeb7", "index": "0x0703", - "section": "contracts", "method": "ContractEmitted", - "transactionHash": "0x1080eb1f8de1ee5b0c1bd584924951c38b998bc7596773ef5e1a92908409a17f", - "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x33766995fd9b44bd45f351b3abd7e5041960638db0075c84ab7af1a734e20d1b, 0x5445726332303a3a5472616e736665723a3a66726f6d00000000000000000000]" - }, - { - "id": "509f2fb6-ed61-5dc7-a567-3cfa55e1fa65", - "index": "0x0703", "section": "contracts", - "method": "ContractEmitted", - "transactionHash": "0x2a009bf5fdc388f10953cba4661c3ca74e0252c1fcae6ba7f39f4eb7be707caa", - "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x2b00c7d40fe6d84d660f3e6bed90f218e022a0909f7e1a7ea35ada8b6e003564, 0xda2d695d3b5a304e0039e7fc4419c34fa0c1f239189c99bb72a6484f1634782b]" + "timestamp": 1666888006111, + "topics": "[0x0045726332303a3a5472616e7366657200000000000000000000000000000000, 0x08be862c40d599dc6f4f28076712bb324c0cd2197c30f07459887b41fadff2c8, 0x2b00c7d40fe6d84d660f3e6bed90f218e022a0909f7e1a7ea35ada8b6e003564]", + "transactionHash": "0x33831da6b804e82cd7613e0d780823c7455c773546ea5e76c945ed10a6f6554b", + "data": "[\"5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8\",\"0x0001c40e2006bbebf9022c317f9337ad376e56d392917e5ac1397fe09b07c765c050018eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48005039278c0400000000000000000000\"]", + "decodedData": "{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"to\",\"type\":{\"sub\":{\"docs\":[],\"info\":10,\"type\":\"AccountId\",\"namespace\":\"ink_env::types::AccountId\",\"lookupIndex\":2,\"lookupNameRoot\":\"InkEnvAccountId\"},\"docs\":[],\"info\":9,\"type\":\"Option\",\"namespace\":\"Option\",\"lookupIndex\":11}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"index\":0,\"identifier\":\"Transfer\"}}", + "formattedData": "{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}" } ] } } ``` - **decodeEvents**: Decodes the events data for a specific contract. Requires that the contract's metadata was already uploaded using the mutation **uploadMetadata** + **getContract**: Retrieves a contract by address ```graphql query { - decodeEvents(contractAddress: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") + getContract(address: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") { + address + metadata + hasMetadata + } } ``` @@ -435,18 +626,26 @@ query { ```graphql { "data": { - "decodeEvents": "[{\"args\":[null,\"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\",\"0x000000000000000000038d7ea4c68000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}},{\"args\":[\"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000001c6bf52634000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}}]" + "getContract": { + "address": "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc", + "metadata": "{\n \"source\": {\n \"hash\": ... }\n}\n", + "hasMetadata": true + } } } ``` - **getContract**: Retrieves a contract by address + **getContracts**: Retrieves a list of contracts ```graphql query { - getContract(address: "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc") { + getContracts(skip: 0, take: 10) { address metadata + hasMetadata + events { + method + } } } ``` @@ -456,9 +655,75 @@ query { ```graphql { "data": { - "getContract": { - "address": "5G24svh2w4QXNhsHU5XBxf8N3Sw2MPu7sAemofv1bCuyxAzc", - "metadata": "{\n \"source\": {\n \"hash\": ... }\n}\n" + "getContracts": [ + { + "address": "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", + "hasMetadata": true, + "metadata": "{ ... }", + "events": [ + { + "method": "ContractEmitted" + }, + ] + } + ] + } +} +``` + + **getContractQueries**: Retrieves a contract. If this contract has uploaded metadata it will also retrieve the queries and transaction methods that can be executed. + +```graphql +query { + getContractQueries(address: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8") { + address + hasMetadata + queries { + args + docs + method + name + } + } +} +``` + + Response: + +```graphql +{ + "data": { + "getContractQueries": { + "address": "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", + "hasMetadata": true, + "queries": [ + { + "args": [], + "docs": [ + " Returns the total token supply." + ], + "method": "totalSupply", + "name": "Total supply" + }, + { + "args": [ + "{\"name\":\"to\",\"type\":{\"info\":10,\"type\":\"AccountId\"}}", + "{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}" + ], + "docs": [ + " Transfers `value` amount of tokens from the caller's account to account `to`.", + "", + " On success a `Transfer` event is emitted.", + "", + " # Errors", + "", + " Returns `InsufficientBalance` error if there are not enough tokens on", + " the caller's account balance." + ], + "method": "transfer", + "name": "Transfer" + } + ] } } } @@ -466,6 +731,45 @@ query { ### **Mutations** + **decodeEvent**: Decodes the event data for a specific event. Requires that the contract's metadata was already uploaded using the mutation **uploadMetadata** + +```graphql +mutation { + decodeEvent( + contractAddress: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8" + id: "81735cc9-76d3-5984-83af-5872bc9eaeb7" + ) +} +``` + + Response: + +```graphql +{ + "data": { + "decodeEvent": "[{\"decodedData\":{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}},\"formattedData\":{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}}]" + } +} +``` + + **decodeEvents**: Decodes the events data for a specific contract (use 'skip' and 'take' to select the events and 'orderAsc' to order by timestamp). Requires that the contract's metadata was already uploaded using the mutation **uploadMetadata** + +```graphql +mutation { + decodeEvents(contract: "5DfG5TyaffuJ78rHP71cvkYEtktRkpeMiJNJyxd8Q5924GR8", skip: 0, take: 1, orderAsc: false) +} +``` + + Response: + +```graphql +{ + "data": { + "decodeEvents": "[{\"decodedData\":{\"args\":[\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"0x00000000000000000000048c27395000\"],\"event\":{\"args\":[{\"name\":\"from\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"to\",\"type\":{\"info\":9,\"lookupIndex\":11,\"type\":\"Option\",\"docs\":[],\"namespace\":\"Option\",\"sub\":{\"info\":10,\"lookupIndex\":2,\"type\":\"AccountId\",\"docs\":[],\"namespace\":\"ink_env::types::AccountId\",\"lookupNameRoot\":\"InkEnvAccountId\"}}},{\"name\":\"value\",\"type\":{\"info\":10,\"type\":\"Balance\"}}],\"docs\":[\" Event emitted when a token transfer occurs.\"],\"identifier\":\"Transfer\",\"index\":0}},\"formattedData\":{\"from\":\"5GVmSPghWsjACADGYi78dmhuZEgfgDwfixR7BM3aMEoNuTBc\",\"to\":\"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty\",\"value\":5}}]" + } +} +``` + **uploadMetadata**: To decode events it is necessary to upload the contract's ABI. Passing a base64 string ABI to this mutation will save that to DB. After that run a **decodeEvents** query to see the decoded data on the events. ```graphql @@ -619,7 +923,7 @@ Example of an ERC20 contract metadata: ... ``` -Once it is uploaded the events can be decoded using the _decodeEvents_ query that can be found on section **Queries**. +Once it is uploaded the events can be decoded using the _decodeEvent_ or _decodeEvents_ mutation that can be found on section **Mutations**. **Note**: The metadata should be uploaded as a **base64** string. @@ -659,9 +963,9 @@ Contributions welcome! See [Contributing](CONTRIBUTING.md). ## Collaborators -* [__Jose Ramirez__](https://github.com/0xslipk) -* [__Fernando Sirni__](https://github.com/fersirni) -* [__Ruben Gutierrez__](https://github.com/RubenGutierrezC) +- [**Jose Ramirez**](https://github.com/0xslipk) +- [**Fernando Sirni**](https://github.com/fersirni) +- [**Ruben Gutierrez**](https://github.com/RubenGutierrezC) ## License