Call API for block info and parse script in frontend
Diff
package-lock.json | 6 ++++++
frontend/package-lock.json | 536 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
frontend/package.json | 3 ++-
frontend/svelte.config.js | 1 +
frontend/src/hooks.ts | 1 -
frontend/src/i18n.ts | 8 --------
frontend/src/i18n/en.json | 29 -----------------------------
frontend/src/lib/bitcoinScript.ts | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
frontend/src/lib/i18n.ts | 16 ++++++++++++++++
frontend/src/routes/__layout.svelte | 17 ++++++++++++++++-
frontend/src/routes/index.svelte | 44 +++++++++++++++++++++++++-------------------
web-api/src/database/blocks.rs | 31 +++++++++++++++++++++++++++++--
web-api/src/database/transactions.rs | 12 +++++++++++-
web-api/src/methods/block.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
web-api/src/methods/mod.rs | 1 +
frontend/src/lib/i18n/en.json | 29 +++++++++++++++++++++++++++++
frontend/src/routes/block/[id].svelte | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 files changed, 696 insertions(+), 334 deletions(-)
@@ -1,0 +1,6 @@
{
"name": "list-blocks",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}
@@ -8,7 +8,8 @@
"name": "list-blocks-frontend",
"version": "0.0.1",
"dependencies": {
"svelte-i18n": "^3.4.0"
"buffer": "^6.0.3",
"sveltekit-i18n": "^2.2.1"
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
@@ -51,50 +52,6 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@formatjs/ecma402-abstract": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz",
"integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==",
"dependencies": {
"@formatjs/intl-localematcher": "0.2.25",
"tslib": "^2.1.0"
}
},
"node_modules/@formatjs/fast-memoize": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz",
"integrity": "sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@formatjs/icu-messageformat-parser": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz",
"integrity": "sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==",
"dependencies": {
"@formatjs/ecma402-abstract": "1.11.4",
"@formatjs/icu-skeleton-parser": "1.3.6",
"tslib": "^2.1.0"
}
},
"node_modules/@formatjs/icu-skeleton-parser": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz",
"integrity": "sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==",
"dependencies": {
"@formatjs/ecma402-abstract": "1.11.4",
"tslib": "^2.1.0"
}
},
"node_modules/@formatjs/intl-localematcher": {
"version": "0.2.25",
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz",
"integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.9.5",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
@@ -236,12 +193,12 @@
}
},
"node_modules/@sveltejs/kit": {
"version": "1.0.0-next.333",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.333.tgz",
"integrity": "sha512-gaj68NCVVKnzDPALzNbaP2xMaNvCZYxoreEGF6P8/bPAh4X6yB5OrgmtensoizPxSJW6d/Lz4LVw71LPmrQgkw==",
"version": "1.0.0-next.336",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.336.tgz",
"integrity": "sha512-DfERqclfwI8Gdx8/p5qIU3vwEOQfWqC8+BXR12bNykbXFM1k8koDplRDpmGzcsXyhslf83j+RmchnkifbNLjsw==",
"dev": true,
"dependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.32",
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.44",
"chokidar": "^3.5.3",
"sade": "^1.7.4",
"vite": "^2.9.0"
@@ -281,8 +238,24 @@
"diff-match-patch": {
"optional": true
}
}
},
"node_modules/@sveltekit-i18n/base": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@sveltekit-i18n/base/-/base-1.2.1.tgz",
"integrity": "sha512-F8gqG2+KAOeT0o2wYlUrW3TRCX7zaD7rBy/1CEVNw0irfw9TgFf/ODmhubkHHT3+6Zk+SMz8RNgeuffBfAMbJw==",
"optionalDependencies": {
"@sveltekit-i18n/parser-default": "^1.x"
},
"peerDependencies": {
"svelte": "^3.x"
}
},
"node_modules/@sveltekit-i18n/parser-default": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@sveltekit-i18n/parser-default/-/parser-default-1.0.3.tgz",
"integrity": "sha512-HheveklTjp3hxpYQhoHfyA6B4bQaUeSV5MQf2usIv/58UF2jY/YqhCAWj9bDBjufbuZc5pSz4BXvdX3WVT+viA=="
},
"node_modules/@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
@@ -290,9 +263,9 @@
"dev": true
},
"node_modules/@types/node": {
"version": "17.0.34",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.34.tgz",
"integrity": "sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA==",
"version": "17.0.35",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==",
"dev": true
},
"node_modules/@types/pug": {
@@ -311,14 +284,14 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.24.0.tgz",
"integrity": "sha512-6bqFGk6wa9+6RrU++eLknKyDqXU1Oc8nyoLu5a1fU17PNRJd9UBr56rMF7c4DRaRtnarlkQ4jwxUbvBo8cNlpw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.25.0.tgz",
"integrity": "sha512-icYrFnUzvm+LhW0QeJNKkezBu6tJs9p/53dpPLFH8zoM9w1tfaKzVurkPotEpAqQ8Vf8uaFyL5jHd0Vs6Z0ZQg==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.24.0",
"@typescript-eslint/type-utils": "5.24.0",
"@typescript-eslint/utils": "5.24.0",
"@typescript-eslint/scope-manager": "5.25.0",
"@typescript-eslint/type-utils": "5.25.0",
"@typescript-eslint/utils": "5.25.0",
"debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0",
@@ -344,14 +317,14 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.24.0.tgz",
"integrity": "sha512-4q29C6xFYZ5B2CXqSBBdcS0lPyfM9M09DoQLtHS5kf+WbpV8pBBhHDLNhXfgyVwFnhrhYzOu7xmg02DzxeF2Uw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.25.0.tgz",
"integrity": "sha512-r3hwrOWYbNKP1nTcIw/aZoH+8bBnh/Lh1iDHoFpyG4DnCpvEdctrSl6LOo19fZbzypjQMHdajolxs6VpYoChgA==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.24.0",
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/typescript-estree": "5.24.0",
"@typescript-eslint/scope-manager": "5.25.0",
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/typescript-estree": "5.25.0",
"debug": "^4.3.4"
},
"engines": {
@@ -371,13 +344,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.24.0.tgz",
"integrity": "sha512-WpMWipcDzGmMzdT7NtTjRXFabx10WleLUGrJpuJLGaxSqpcyq5ACpKSD5VE40h2nz3melQ91aP4Du7lh9FliCA==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.25.0.tgz",
"integrity": "sha512-p4SKTFWj+2VpreUZ5xMQsBMDdQ9XdRvODKXN4EksyBjFp2YvQdLkyHqOffakYZPuWJUDNu3jVXtHALDyTv3cww==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/visitor-keys": "5.24.0"
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/visitor-keys": "5.25.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -388,12 +361,12 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.24.0.tgz",
"integrity": "sha512-uGi+sQiM6E5CeCZYBXiaIvIChBXru4LZ1tMoeKbh1Lze+8BO9syUG07594C4lvN2YPT4KVeIupOJkVI+9/DAmQ==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.25.0.tgz",
"integrity": "sha512-B6nb3GK3Gv1Rsb2pqalebe/RyQoyG/WDy9yhj8EE0Ikds4Xa8RR28nHz+wlt4tMZk5bnAr0f3oC8TuDAd5CPrw==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "5.24.0",
"@typescript-eslint/utils": "5.25.0",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
@@ -414,9 +387,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.24.0.tgz",
"integrity": "sha512-Tpg1c3shTDgTmZd3qdUyd+16r/pGmVaVEbLs+ufuWP0EruVbUiEOmpBBQxBb9a8iPRxi8Rb2oiwOxuZJzSq11A==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.25.0.tgz",
"integrity": "sha512-7fWqfxr0KNHj75PFqlGX24gWjdV/FDBABXL5dyvBOWHpACGyveok8Uj4ipPX/1fGU63fBkzSIycEje4XsOxUFA==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -427,13 +400,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.24.0.tgz",
"integrity": "sha512-zcor6vQkQmZAQfebSPVwUk/FD+CvnsnlfKXYeQDsWXRF+t7SBPmIfNia/wQxCSeu1h1JIjwV2i9f5/DdSp/uDw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.25.0.tgz",
"integrity": "sha512-MrPODKDych/oWs/71LCnuO7NyR681HuBly2uLnX3r5i4ME7q/yBqC4hW33kmxtuauLTM0OuBOhhkFaxCCOjEEw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/visitor-keys": "5.24.0",
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/visitor-keys": "5.25.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -454,15 +427,15 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.24.0.tgz",
"integrity": "sha512-K05sbWoeCBJH8KXu6hetBJ+ukG0k2u2KlgD3bN+v+oBKm8adJqVHpSSLHNzqyuv0Lh4GVSAUgZ5lB4icmPmWLw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.25.0.tgz",
"integrity": "sha512-qNC9bhnz/n9Kba3yI6HQgQdBLuxDoMgdjzdhSInZh6NaDnFpTUlwNGxplUFWfY260Ya0TRPvkg9dd57qxrJI9g==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.24.0",
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/typescript-estree": "5.24.0",
"@typescript-eslint/scope-manager": "5.25.0",
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/typescript-estree": "5.25.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
@@ -478,12 +451,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.24.0.tgz",
"integrity": "sha512-qzGwSXMyMnogcAo+/2fU+jhlPPVMXlIH2PeAonIKjJSoDKl1+lJVvG5Z5Oud36yU0TWK2cs1p/FaSN5J2OUFYA==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.25.0.tgz",
"integrity": "sha512-yd26vFgMsC4h2dgX4+LR+GeicSKIfUvZREFLf3DDjZPtqgLx5AJZr6TetMNwFP9hcKreTTeztQYBTNbNoOycwA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/types": "5.25.0",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
@@ -659,6 +632,25 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/binary-extensions": {
"version": "2.2.0",
@@ -718,6 +710,29 @@
},
"engines": {
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-crc32": {
@@ -883,6 +898,7 @@
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -1568,7 +1584,8 @@
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"node_modules/esutils": {
"version": "2.0.3",
@@ -1760,7 +1777,8 @@
"node_modules/globalyzer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q=="
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
"dev": true
},
"node_modules/globby": {
"version": "11.1.0",
@@ -1785,7 +1803,8 @@
"node_modules/globrex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"dev": true
},
"node_modules/graceful-fs": {
"version": "4.2.10",
@@ -1813,6 +1832,25 @@
"engines": {
"node": ">=8"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ignore": {
"version": "5.2.0",
@@ -1869,17 +1907,6 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/intl-messageformat": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.13.0.tgz",
"integrity": "sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==",
"dependencies": {
"@formatjs/ecma402-abstract": "1.11.4",
"@formatjs/fast-memoize": "1.2.1",
"@formatjs/icu-messageformat-parser": "2.1.0",
"tslib": "^2.1.0"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
@@ -2091,6 +2118,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true,
"engines": {
"node": ">=4"
}
@@ -2251,9 +2279,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.13",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz",
"integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==",
"version": "8.4.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
"integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
"dev": true,
"funding": [
{
@@ -2266,7 +2294,7 @@
}
],
"dependencies": {
"nanoid": "^3.3.3",
"nanoid": "^3.3.4",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
@@ -2520,9 +2548,9 @@
}
},
"node_modules/rollup": {
"version": "2.73.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.73.0.tgz",
"integrity": "sha512-h/UngC3S4Zt28mB3g0+2YCMegT5yoftnQplwzPqGZcKvlld5e+kT/QRmJiL+qxGyZKOYpgirWGdLyEO1b0dpLQ==",
"version": "2.74.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.74.1.tgz",
"integrity": "sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
@@ -2561,6 +2589,7 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
"integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
"dev": true,
"dependencies": {
"mri": "^1.1.0"
},
@@ -2593,9 +2622,9 @@
}
},
"node_modules/sass": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.51.0.tgz",
"integrity": "sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==",
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.52.0.tgz",
"integrity": "sha512-6EnTglag2oVD8sNJCxUi2Jd3ICH9tJ5Mqudt/gIZNBR2uKJUBZuTpW9O1t04SkDLP7VFa76FCWTV2rwchqM8Kw==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -2784,27 +2813,6 @@
},
"peerDependencies": {
"svelte": ">=3.19.0"
}
},
"node_modules/svelte-i18n": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/svelte-i18n/-/svelte-i18n-3.4.0.tgz",
"integrity": "sha512-590N+YIRlebDT3fXmuAxd4guQZLR3vm4kCs5UhWYmw3SxOlJNZ7HwYYiw6d4jDr7P+Cx7DSopk1Z1K9wn8B6EA==",
"dependencies": {
"deepmerge": "^4.2.2",
"estree-walker": "^2.0.1",
"intl-messageformat": "^9.3.15",
"sade": "^1.7.4",
"tiny-glob": "^0.2.6"
},
"bin": {
"svelte-i18n": "dist/cli.js"
},
"engines": {
"node": ">= 11.15.0"
},
"peerDependencies": {
"svelte": "^3.25.1"
}
},
"node_modules/svelte-preprocess": {
@@ -2880,6 +2888,18 @@
"dev": true,
"dependencies": {
"sourcemap-codec": "^1.4.8"
}
},
"node_modules/sveltekit-i18n": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/sveltekit-i18n/-/sveltekit-i18n-2.2.1.tgz",
"integrity": "sha512-1CyaRN6dBvp467JjBdji+nJf+7pZ3myFu+2YaCuGSAt09Cvt5ndfRbzy+aAd5WJdk6Lu/hnPEE7ZZFauTbDRNw==",
"dependencies": {
"@sveltekit-i18n/base": "1.2.1",
"@sveltekit-i18n/parser-default": "1.0.3"
},
"peerDependencies": {
"svelte": "^3.x"
}
},
"node_modules/tailwindcss": {
@@ -2943,6 +2963,7 @@
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
"dev": true,
"dependencies": {
"globalyzer": "0.1.0",
"globrex": "^0.1.2"
@@ -2963,7 +2984,8 @@
"node_modules/tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
"dev": true
},
"node_modules/tsutils": {
"version": "3.21.0",
@@ -3165,50 +3187,6 @@
"js-yaml": "^4.1.0",
"minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
}
},
"@formatjs/ecma402-abstract": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.4.tgz",
"integrity": "sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==",
"requires": {
"@formatjs/intl-localematcher": "0.2.25",
"tslib": "^2.1.0"
}
},
"@formatjs/fast-memoize": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz",
"integrity": "sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==",
"requires": {
"tslib": "^2.1.0"
}
},
"@formatjs/icu-messageformat-parser": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.0.tgz",
"integrity": "sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==",
"requires": {
"@formatjs/ecma402-abstract": "1.11.4",
"@formatjs/icu-skeleton-parser": "1.3.6",
"tslib": "^2.1.0"
}
},
"@formatjs/icu-skeleton-parser": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.6.tgz",
"integrity": "sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==",
"requires": {
"@formatjs/ecma402-abstract": "1.11.4",
"tslib": "^2.1.0"
}
},
"@formatjs/intl-localematcher": {
"version": "0.2.25",
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.25.tgz",
"integrity": "sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==",
"requires": {
"tslib": "^2.1.0"
}
},
"@humanwhocodes/config-array": {
@@ -3334,12 +3312,12 @@
}
},
"@sveltejs/kit": {
"version": "1.0.0-next.333",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.333.tgz",
"integrity": "sha512-gaj68NCVVKnzDPALzNbaP2xMaNvCZYxoreEGF6P8/bPAh4X6yB5OrgmtensoizPxSJW6d/Lz4LVw71LPmrQgkw==",
"version": "1.0.0-next.336",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.336.tgz",
"integrity": "sha512-DfERqclfwI8Gdx8/p5qIU3vwEOQfWqC8+BXR12bNykbXFM1k8koDplRDpmGzcsXyhslf83j+RmchnkifbNLjsw==",
"dev": true,
"requires": {
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.32",
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.44",
"chokidar": "^3.5.3",
"sade": "^1.7.4",
"vite": "^2.9.0"
@@ -3358,6 +3336,19 @@
"magic-string": "^0.26.1",
"svelte-hmr": "^0.14.11"
}
},
"@sveltekit-i18n/base": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@sveltekit-i18n/base/-/base-1.2.1.tgz",
"integrity": "sha512-F8gqG2+KAOeT0o2wYlUrW3TRCX7zaD7rBy/1CEVNw0irfw9TgFf/ODmhubkHHT3+6Zk+SMz8RNgeuffBfAMbJw==",
"requires": {
"@sveltekit-i18n/parser-default": "^1.x"
}
},
"@sveltekit-i18n/parser-default": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@sveltekit-i18n/parser-default/-/parser-default-1.0.3.tgz",
"integrity": "sha512-HheveklTjp3hxpYQhoHfyA6B4bQaUeSV5MQf2usIv/58UF2jY/YqhCAWj9bDBjufbuZc5pSz4BXvdX3WVT+viA=="
},
"@types/json-schema": {
"version": "7.0.11",
@@ -3366,9 +3357,9 @@
"dev": true
},
"@types/node": {
"version": "17.0.34",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.34.tgz",
"integrity": "sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA==",
"version": "17.0.35",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz",
"integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==",
"dev": true
},
"@types/pug": {
@@ -3387,14 +3378,14 @@
}
},
"@typescript-eslint/eslint-plugin": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.24.0.tgz",
"integrity": "sha512-6bqFGk6wa9+6RrU++eLknKyDqXU1Oc8nyoLu5a1fU17PNRJd9UBr56rMF7c4DRaRtnarlkQ4jwxUbvBo8cNlpw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.25.0.tgz",
"integrity": "sha512-icYrFnUzvm+LhW0QeJNKkezBu6tJs9p/53dpPLFH8zoM9w1tfaKzVurkPotEpAqQ8Vf8uaFyL5jHd0Vs6Z0ZQg==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.24.0",
"@typescript-eslint/type-utils": "5.24.0",
"@typescript-eslint/utils": "5.24.0",
"@typescript-eslint/scope-manager": "5.25.0",
"@typescript-eslint/type-utils": "5.25.0",
"@typescript-eslint/utils": "5.25.0",
"debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0",
@@ -3404,52 +3395,52 @@
}
},
"@typescript-eslint/parser": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.24.0.tgz",
"integrity": "sha512-4q29C6xFYZ5B2CXqSBBdcS0lPyfM9M09DoQLtHS5kf+WbpV8pBBhHDLNhXfgyVwFnhrhYzOu7xmg02DzxeF2Uw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.25.0.tgz",
"integrity": "sha512-r3hwrOWYbNKP1nTcIw/aZoH+8bBnh/Lh1iDHoFpyG4DnCpvEdctrSl6LOo19fZbzypjQMHdajolxs6VpYoChgA==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.24.0",
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/typescript-estree": "5.24.0",
"@typescript-eslint/scope-manager": "5.25.0",
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/typescript-estree": "5.25.0",
"debug": "^4.3.4"
}
},
"@typescript-eslint/scope-manager": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.24.0.tgz",
"integrity": "sha512-WpMWipcDzGmMzdT7NtTjRXFabx10WleLUGrJpuJLGaxSqpcyq5ACpKSD5VE40h2nz3melQ91aP4Du7lh9FliCA==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.25.0.tgz",
"integrity": "sha512-p4SKTFWj+2VpreUZ5xMQsBMDdQ9XdRvODKXN4EksyBjFp2YvQdLkyHqOffakYZPuWJUDNu3jVXtHALDyTv3cww==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/visitor-keys": "5.24.0"
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/visitor-keys": "5.25.0"
}
},
"@typescript-eslint/type-utils": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.24.0.tgz",
"integrity": "sha512-uGi+sQiM6E5CeCZYBXiaIvIChBXru4LZ1tMoeKbh1Lze+8BO9syUG07594C4lvN2YPT4KVeIupOJkVI+9/DAmQ==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.25.0.tgz",
"integrity": "sha512-B6nb3GK3Gv1Rsb2pqalebe/RyQoyG/WDy9yhj8EE0Ikds4Xa8RR28nHz+wlt4tMZk5bnAr0f3oC8TuDAd5CPrw==",
"dev": true,
"requires": {
"@typescript-eslint/utils": "5.24.0",
"@typescript-eslint/utils": "5.25.0",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/types": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.24.0.tgz",
"integrity": "sha512-Tpg1c3shTDgTmZd3qdUyd+16r/pGmVaVEbLs+ufuWP0EruVbUiEOmpBBQxBb9a8iPRxi8Rb2oiwOxuZJzSq11A==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.25.0.tgz",
"integrity": "sha512-7fWqfxr0KNHj75PFqlGX24gWjdV/FDBABXL5dyvBOWHpACGyveok8Uj4ipPX/1fGU63fBkzSIycEje4XsOxUFA==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.24.0.tgz",
"integrity": "sha512-zcor6vQkQmZAQfebSPVwUk/FD+CvnsnlfKXYeQDsWXRF+t7SBPmIfNia/wQxCSeu1h1JIjwV2i9f5/DdSp/uDw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.25.0.tgz",
"integrity": "sha512-MrPODKDych/oWs/71LCnuO7NyR681HuBly2uLnX3r5i4ME7q/yBqC4hW33kmxtuauLTM0OuBOhhkFaxCCOjEEw==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/visitor-keys": "5.24.0",
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/visitor-keys": "5.25.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -3458,26 +3449,26 @@
}
},
"@typescript-eslint/utils": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.24.0.tgz",
"integrity": "sha512-K05sbWoeCBJH8KXu6hetBJ+ukG0k2u2KlgD3bN+v+oBKm8adJqVHpSSLHNzqyuv0Lh4GVSAUgZ5lB4icmPmWLw==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.25.0.tgz",
"integrity": "sha512-qNC9bhnz/n9Kba3yI6HQgQdBLuxDoMgdjzdhSInZh6NaDnFpTUlwNGxplUFWfY260Ya0TRPvkg9dd57qxrJI9g==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.24.0",
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/typescript-estree": "5.24.0",
"@typescript-eslint/scope-manager": "5.25.0",
"@typescript-eslint/types": "5.25.0",
"@typescript-eslint/typescript-estree": "5.25.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.24.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.24.0.tgz",
"integrity": "sha512-qzGwSXMyMnogcAo+/2fU+jhlPPVMXlIH2PeAonIKjJSoDKl1+lJVvG5Z5Oud36yU0TWK2cs1p/FaSN5J2OUFYA==",
"version": "5.25.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.25.0.tgz",
"integrity": "sha512-yd26vFgMsC4h2dgX4+LR+GeicSKIfUvZREFLf3DDjZPtqgLx5AJZr6TetMNwFP9hcKreTTeztQYBTNbNoOycwA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.24.0",
"@typescript-eslint/types": "5.25.0",
"eslint-visitor-keys": "^3.3.0"
}
},
@@ -3593,6 +3584,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"binary-extensions": {
"version": "2.2.0",
@@ -3630,6 +3626,15 @@
"escalade": "^3.1.1",
"node-releases": "^2.0.3",
"picocolors": "^1.0.0"
}
},
"buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"buffer-crc32": {
@@ -3738,7 +3743,8 @@
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true
},
"defined": {
"version": "1.0.0",
@@ -4156,7 +4162,8 @@
"estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"esutils": {
"version": "2.0.3",
@@ -4304,7 +4311,8 @@
"globalyzer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q=="
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
"dev": true
},
"globby": {
"version": "11.1.0",
@@ -4323,7 +4331,8 @@
"globrex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"dev": true
},
"graceful-fs": {
"version": "4.2.10",
@@ -4346,6 +4355,11 @@
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@@ -4389,17 +4403,6 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"intl-messageformat": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.13.0.tgz",
"integrity": "sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==",
"requires": {
"@formatjs/ecma402-abstract": "1.11.4",
"@formatjs/fast-memoize": "1.2.1",
"@formatjs/icu-messageformat-parser": "2.1.0",
"tslib": "^2.1.0"
}
},
"is-binary-path": {
"version": "2.1.0",
@@ -4562,7 +4565,8 @@
"mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true
},
"mrmime": {
"version": "1.0.0",
@@ -4681,12 +4685,12 @@
"dev": true
},
"postcss": {
"version": "8.4.13",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz",
"integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==",
"version": "8.4.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
"integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
"dev": true,
"requires": {
"nanoid": "^3.3.3",
"nanoid": "^3.3.4",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
}
@@ -4826,9 +4830,9 @@
}
},
"rollup": {
"version": "2.73.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.73.0.tgz",
"integrity": "sha512-h/UngC3S4Zt28mB3g0+2YCMegT5yoftnQplwzPqGZcKvlld5e+kT/QRmJiL+qxGyZKOYpgirWGdLyEO1b0dpLQ==",
"version": "2.74.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.74.1.tgz",
"integrity": "sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==",
"dev": true,
"requires": {
"fsevents": "~2.3.2"
@@ -4847,6 +4851,7 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
"integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
"dev": true,
"requires": {
"mri": "^1.1.0"
}
@@ -4875,9 +4880,9 @@
}
},
"sass": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.51.0.tgz",
"integrity": "sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==",
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.52.0.tgz",
"integrity": "sha512-6EnTglag2oVD8sNJCxUi2Jd3ICH9tJ5Mqudt/gIZNBR2uKJUBZuTpW9O1t04SkDLP7VFa76FCWTV2rwchqM8Kw==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
@@ -5005,18 +5010,6 @@
"integrity": "sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==",
"dev": true,
"requires": {}
},
"svelte-i18n": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/svelte-i18n/-/svelte-i18n-3.4.0.tgz",
"integrity": "sha512-590N+YIRlebDT3fXmuAxd4guQZLR3vm4kCs5UhWYmw3SxOlJNZ7HwYYiw6d4jDr7P+Cx7DSopk1Z1K9wn8B6EA==",
"requires": {
"deepmerge": "^4.2.2",
"estree-walker": "^2.0.1",
"intl-messageformat": "^9.3.15",
"sade": "^1.7.4",
"tiny-glob": "^0.2.6"
}
},
"svelte-preprocess": {
"version": "4.10.6",
@@ -5043,6 +5036,15 @@
}
}
},
"sveltekit-i18n": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/sveltekit-i18n/-/sveltekit-i18n-2.2.1.tgz",
"integrity": "sha512-1CyaRN6dBvp467JjBdji+nJf+7pZ3myFu+2YaCuGSAt09Cvt5ndfRbzy+aAd5WJdk6Lu/hnPEE7ZZFauTbDRNw==",
"requires": {
"@sveltekit-i18n/base": "1.2.1",
"@sveltekit-i18n/parser-default": "1.0.3"
}
},
"tailwindcss": {
"version": "3.0.24",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz",
@@ -5093,6 +5095,7 @@
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
"dev": true,
"requires": {
"globalyzer": "0.1.0",
"globrex": "^0.1.2"
@@ -5110,7 +5113,8 @@
"tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
"dev": true
},
"tsutils": {
"version": "3.21.0",
@@ -34,6 +34,7 @@
},
"type": "module",
"dependencies": {
"svelte-i18n": "^3.4.0"
"buffer": "^6.0.3",
"sveltekit-i18n": "^2.2.1"
}
}
@@ -10,6 +10,7 @@
}),
kit: {
adapter: adapter(),
},
};
@@ -1,1 +1,0 @@
import "./i18n";
@@ -1,8 +1,0 @@
import { getLocaleFromNavigator, init, register } from "svelte-i18n";
register("en", () => import("./i18n/en.json"));
init({
fallbackLocale: "en",
initialLocale: getLocaleFromNavigator(),
});
@@ -1,29 +1,0 @@
{
"site_name": "blocks.ls",
"nav": {
"dashboard": "Dashboard",
"blocks": "Blocks",
"txns": "Transactions"
},
"home": {
"latest_blocks": {
"header": "Latest Blocks",
"table": {
"height": "Height",
"timestamp": "Timestamp",
"txns": "Transactions",
"size": "Size (KB)",
"weight": "Weight (KWU)"
}
},
"latest_txns": {
"header": "Latest Transactions",
"table": {
"txn_id": "Transaction ID",
"value": "Value",
"size": "Size",
"fee": "Fee"
}
}
}
}
@@ -1,0 +1,148 @@
import { Buffer } from "buffer/";
export function hexToAsm(hex: string) {
const bytes = Buffer.from(hex, 'hex');
const out = [];
for (let i = 0; i < bytes.length; i++) {
const byte = bytes[i];
if (byte < 0x02) {
out.push(byte);
continue;
}
if (byte >= 0x52 && byte <= 0x60) {
out.push(byte-0x50)
continue;
}
if(byte >= 0x02 && byte <= 0x4b) {
out.push(bytes.slice(i + 1, i + 1 + byte).toString("hex"));
i += byte;
}
out.push(Operation[byte] || byte.toString(16))
}
return out;
}
enum Operation {
OP_FALSE = 0x00,
OP_PUSHDATA1 = 0x4c,
OP_PUSHDATA2 = 0x4d,
OP_PUSHDATA4 = 0x4e,
OP_1NEGATE = 0x4f,
OP_RESERVED = 0x50,
OP_TRUE = 0x51,
OP_2 = 0x52,
OP_3 = 0x53,
OP_4 = 0x54,
OP_5 = 0x55,
OP_6 = 0x56,
OP_7 = 0x57,
OP_8 = 0x58,
OP_9 = 0x59,
OP_10 = 0x5a,
OP_11 = 0x5b,
OP_12 = 0x5c,
OP_13 = 0x5d,
OP_14 = 0x5e,
OP_15 = 0x5f,
OP_16 = 0x60,
OP_NOP = 0x61,
OP_VER = 0x62,
OP_IF = 0x63,
OP_NOTIF = 0x64,
OP_VERIF = 0x65,
OP_VERNOTIF = 0x66,
OP_ELSE = 0x67,
OP_ENDIF = 0x68,
OP_VERIFY = 0x69,
OP_RETURN = 0x6a,
OP_TOALTSTACK = 0x6b,
OP_FROMALTSTACK = 0x6c,
OP_2DROP = 0x6d,
OP_2DUP = 0x6e,
OP_3DUP = 0x6f,
OP_2OVER = 0x70,
OP_2ROT = 0x71,
OP_2SWAP = 0x72,
OP_IFDUP = 0x73,
OP_DEPTH = 0x74,
OP_DROP = 0x75,
OP_DUP = 0x76,
OP_NIP = 0x77,
OP_OVER = 0x78,
OP_PICK = 0x79,
OP_ROLL = 0x7a,
OP_ROT = 0x7b,
OP_SWAP = 0x7c,
OP_TUCK = 0x7d,
OP_CAT = 0x7e,
OP_SUBSTR = 0x7f,
OP_LEFT = 0x80,
OP_RIGHT = 0x81,
OP_SIZE = 0x82,
OP_INVERT = 0x83,
OP_AND = 0x84,
OP_OR = 0x85,
OP_XOR = 0x86,
OP_EQUAL = 0x87,
OP_EQUALVERIFY = 0x88,
OP_RESERVED1 = 0x89,
OP_RESERVED2 = 0x8a,
OP_1ADD = 0x8b,
OP_1SUB = 0x8c,
OP_2MUL = 0x8d,
OP_2DIV = 0x8e,
OP_NEGATE = 0x8f,
OP_ABS = 0x90,
OP_NOT = 0x91,
OP_0NOTEQUAL = 0x92,
OP_ADD = 0x93,
OP_SUB = 0x94,
OP_MUL = 0x95,
OP_DIV = 0x96,
OP_MOD = 0x97,
OP_LSHIFT = 0x98,
OP_RSHIFT = 0x99,
OP_BOOLAND = 0x9a,
OP_BOOLOR = 0x9b,
OP_NUMEQUAL = 0x9c,
OP_NUMEQUALVERIFY = 0x9d,
OP_NUMNOTEQUAL = 0x9e,
OP_LESSTHAN = 0x9f,
OP_GREATERTHAN = 0xa0,
OP_LESSTHANOREQUAL = 0xa1,
OP_GREATERTHANOREQUAL = 0xa2,
OP_MIN = 0xa3,
OP_MAX = 0xa4,
OP_WITHIN = 0xa5,
OP_RIPEMD160 = 0xa6,
OP_SHA1 = 0xa7,
OP_SHA256 = 0xa8,
OP_HASH160 = 0xa9,
OP_HASH256 = 0xaa,
OP_CODESEPARATOR = 0xab,
OP_CHECKSIG = 0xac,
OP_CHECKSIGVERIFY = 0xad,
OP_CHECKMULTISIG = 0xae,
OP_CHECKMULTISIGVERIFY = 0xaf,
OP_NOP1 = 0xb0,
OP_CHECKLOCKTIMEVERIFY = 0xb1,
OP_CHECKSEQUENCEVERIFY = 0xb2,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
OP_NOP7 = 0xb6,
OP_NOP8 = 0xb7,
OP_NOP9 = 0xb8,
OP_NOP10 = 0xb9,
OP_PUBKEYHASH = 0xfd,
OP_PUBKEY = 0xfe,
OP_INVALIDOPCODE = 0xff,
}
@@ -1,0 +1,16 @@
import i18n from 'sveltekit-i18n';
const config = ({
loaders: [
{
locale: 'en',
key: '',
loader: async () => (
await import('./i18n/en.json')
).default,
}
],
});
export const { t, locale, locales, loading, loadTranslations } = new i18n(config);
@@ -1,5 +1,20 @@
<script context="module">
import { locale, loadTranslations } from '$lib/i18n';
export async function load({ url }) {
const { pathname } = url;
const defaultLocale = 'en'; // TODO: get from cookie, user session, ...
const initLocale = locale.get() || defaultLocale;
await loadTranslations(initLocale, pathname);
return {};
}
</script>
<script>
import { _ } from "svelte-i18n";
import { t as _ } from "$lib/i18n";
import "../global.scss";
import { page } from "$app/stores";
</script>
@@ -1,22 +1,26 @@
<script context="module">
export async function load({ fetch }) {
let res = await fetch('http://localhost:3001/block');
if (res.ok) {
return {
props: {
blocks: await res.json()
}
};
}
return {
status: res.status,
error: new Error()
};
}
</script>
<script>
import { _ } from "svelte-i18n";
import { t as _ } from "$lib/i18n";
let blocks = [
{
height: 123457,
timestamp: "12 minutes ago",
transactions: 453,
size: "1094.092",
weight: "3999.574",
},
{
height: 123456,
timestamp: "22 minutes ago",
transactions: 133,
size: "598.233",
weight: "3999.122",
},
];
// TODO: needs loader
export let blocks = [];
let transactions = [
{
@@ -74,9 +78,9 @@
{#each blocks as block}
<tr>
<th><a href={`/block/${block.height}`}>{block.height}</a></th>
<td>{block.timestamp}</td>
<td>{block.transactions}</td>
<td>{block.size}</td>
<td>{block.timestamp}</td>
<td>{block.tx_count}</td>
<td>{block.bits}</td>
<td>{block.weight}</td>
</tr>
{/each}
@@ -1,9 +1,10 @@
use crate::database::{Connection, Result};
use chrono::{DateTime, NaiveDateTime, Utc};
use tokio_postgres::Row;
#[derive(Debug)]
pub struct Block {
pub hash: Vec<u8>,
pub id: i64,
pub height: i64,
pub version: i32,
@@ -11,13 +12,14 @@
pub merkle_root_hash: Vec<u8>,
pub timestamp: NaiveDateTime,
pub bits: i32,
pub nonce: i32,
pub nonce: u32,
pub difficulty: i64,
}
impl Block {
pub fn from_row(row: Row) -> Result<Self> {
Ok(Self {
hash: row.try_get("hash")?,
id: row.try_get("id")?,
height: row.try_get("height")?,
version: row.try_get("version")?,
@@ -25,7 +27,7 @@
merkle_root_hash: row.try_get("merkle_root_hash")?,
timestamp: row.try_get("timestamp")?,
bits: row.try_get("bits")?,
nonce: row.try_get("nonce")?,
nonce: row.try_get::<_, i32>("nonce")? as u32,
difficulty: row.try_get("difficulty")?,
})
}
@@ -37,6 +39,31 @@
.await?;
let height: i64 = row.try_get("height")?;
Ok(u64::try_from(height)?)
}
pub type TransactionCount = i64;
pub async fn fetch_latest_blocks(db: &Connection, count: i64) -> Result<Vec<(Block, TransactionCount)>> {
let blocks = db
.query(
"SELECT blocks.*, COUNT(transactions.id) AS tx_count
FROM blocks
LEFT JOIN transactions
ON transactions.block_id = blocks.id
GROUP BY blocks.id
ORDER BY blocks.height DESC
LIMIT $1",
&[&count],
)
.await?;
blocks
.into_iter()
.map(|row| {
let tx_count = row.try_get("tx_count")?;
Ok((Block::from_row(row)?, tx_count))
})
.collect::<Result<Vec<_>>>()
}
pub async fn fetch_block_by_height(db: &Connection, height: i64) -> Result<Option<Block>> {
@@ -1,5 +1,6 @@
use crate::database::{Connection, Result};
use serde::Deserialize;
use serde::{Deserialize, Deserializer};
use serde::de::Error;
use tokio::time::Instant;
use tokio_postgres::types::Json;
use tokio_postgres::Row;
@@ -34,15 +35,24 @@
#[derive(Deserialize, Debug)]
pub struct TransactionInput {
pub previous_output_tx: Option<TransactionOutput>,
#[serde(deserialize_with = "trim_hex_prefix")]
pub script: String,
}
#[derive(Deserialize, Debug)]
pub struct TransactionOutput {
pub value: i64,
#[serde(deserialize_with = "trim_hex_prefix")]
pub script: String,
pub unspendable: bool,
pub address: Option<String>,
}
fn trim_hex_prefix<'de, D: Deserializer<'de>>(deserializer: D) -> std::result::Result<String, D::Error> {
let mut s = String::deserialize(deserializer)?;
s.remove(0);
s.remove(0);
Ok(s)
}
pub async fn fetch_transactions_for_block(db: &Connection, id: i64) -> Result<Vec<Transaction>> {
@@ -1,3 +1,4 @@
use std::ptr::hash;
use crate::Database;
use axum::extract::Path;
use axum::{Extension, Json};
@@ -5,6 +6,44 @@
use serde::Serialize;
#[derive(Serialize)]
pub struct BlockList {
hash: String,
height: i64,
version: i32,
timestamp: NaiveDateTime,
bits: i32,
nonce: u32,
difficulty: i64,
tx_count: i64,
}
pub async fn list(Extension(database): Extension<Database>) -> Json<Vec<BlockList>> {
let database = database.get().await.unwrap();
let blocks = crate::database::blocks::fetch_latest_blocks(&database, 5).await.unwrap();
Json(
blocks.into_iter()
.map(|(mut block, tx_count)| {
block.hash.reverse();
BlockList {
hash: hex::encode(block.hash),
height: block.height,
version: block.version,
timestamp: block.timestamp,
bits: block.bits,
nonce: block.nonce,
difficulty: block.difficulty,
tx_count
}
})
.collect()
)
}
#[derive(Serialize)]
pub struct Block {
height: i64,
version: i32,
@@ -13,9 +52,10 @@
timestamp: NaiveDateTime,
bits: i32,
nonce: i32,
nonce: u32,
difficulty: i64,
transactions: Vec<Transaction>,
hash: String,
}
#[derive(Serialize)]
@@ -70,7 +110,7 @@
) -> Json<Block> {
let database = database.get().await.unwrap();
let block = crate::database::blocks::fetch_block_by_height(&database, height)
let mut block = crate::database::blocks::fetch_block_by_height(&database, height)
.await
.unwrap()
.unwrap();
@@ -79,8 +119,12 @@
crate::database::transactions::fetch_transactions_for_block(&database, block.id)
.await
.unwrap();
block.hash.reverse();
Json(Block {
hash: hex::encode(block.hash),
height: block.height,
version: block.version,
size: block.size,
@@ -7,5 +7,6 @@
pub fn router() -> Router {
Router::new()
.route("/height", get(height::handle))
.route("/block", get(block::list))
.route("/block/:height", get(block::handle))
}
@@ -1,0 +1,29 @@
{
"site_name": "blocks.ls",
"nav": {
"dashboard": "Dashboard",
"blocks": "Blocks",
"txns": "Transactions"
},
"home": {
"latest_blocks": {
"header": "Latest Blocks",
"table": {
"height": "Height",
"timestamp": "Timestamp",
"txns": "Transactions",
"size": "Size (KB)",
"weight": "Weight (KWU)"
}
},
"latest_txns": {
"header": "Latest Transactions",
"table": {
"txn_id": "Transaction ID",
"value": "Value",
"size": "Size",
"fee": "Fee"
}
}
}
}
@@ -1,7 +1,101 @@
<section>
<h2>single block</h2>
</section>
<script context="module">
export async function load({ fetch, params }) {
let res = await fetch(`http://localhost:3001/block/${params.id}`);
if (res.ok) {
return {
props: {
block: await res.json()
}
};
}
return {
status: res.status,
error: new Error()
};
}
</script>
<script>
import { hexToAsm } from "$lib/bitcoinScript";
export let block = {};
for (let transaction of block.transactions) {
for (let output of transaction.outputs) {
console.log(hexToAsm(output.script));
}
}
</script>
<div>
<section class="p-7">
<h2 class="!p-0 !py-4">Block {block.height}</h2>
<p>{block.hash}</p>
</section>
<section>
<table>
<tbody>
<tr>
<th>Height</th>
<td>{block.height}</td>
</tr>
<tr>
<th>Merkle Root Hash</th>
<td>{block.merkle_root_hash}</td>
</tr>
</tbody>
</table>
</section>
<section class="!bg-transparent">
<h3 class="text-white text-2xl">{block.transactions.length} Transactions</h3>
</section>
{#each block.transactions as transaction}
<section>
<h3 class="text-lg m-2">{transaction.hash}</h3>
<div class="flex">
<table>
<tbody>
{#if transaction.coinbase}
<tr>
<td>Coinbase</td>
</tr>
{:else}
{#each transaction.inputs as input}
<tr>
<td>{input.previous_output?.address || hexToAsm(input.script).join('\n')}</td>
</tr>
{/each}
{/if}
</tbody>
</table>
<div class="text-2xl mx-4 self-center">
→
</div>
<table>
<tbody>
<tr>
{#each transaction.outputs as output}
<td>{output.address || hexToAsm(output.script).join('\n')}</td>
{/each}
</tbody>
</table>
</div>
</section>
{/each}
</div>
<style lang="scss">
@import "../../_section.scss";
@import "../../_table.scss";
section {
@apply text-xs;
}
</style>