{"_id":"@0xflick/tapscript","_rev":"3-d90db368fa1e90be11243d8098c4fb58","name":"@0xflick/tapscript","dist-tags":{"latest":"2.0.1"},"versions":{"1.2.11-0xflick.0":{"name":"@0xflick/tapscript","version":"1.2.11-0xflick.0","description":"A basic library for working with Tapscript, signatures and Bitcoin transactions.","type":"module","main":"./dist/main.cjs","unpkg":"./dist/bundle.min.js","types":"./dist/types/index.d.ts","exports":{"import":"./dist/module.mjs","require":"./dist/main.cjs","types":"./dist/types/index.d.ts"},"scripts":{"build":"rollup -c rollup.config.ts --configPlugin typescript","clean":"rm -rf dist/* coverage .nyc_output","start":"node --trace-deprecation --no-warnings --loader ts-node/esm","scratch":"yarn start test/scratch.ts","lint":"eslint . --ext .ts","fix":"eslint --fix . --ext .ts","tape":"yarn start test/tape.ts","test":"nyc --reporter=lcov --require ts-node/register yarn tape | tap-spec; nyc report ---reporter=text","types":"tsc","release":"yarn test && yarn clean && yarn types && yarn lint && yarn build"},"keywords":["bitcoin","transaction","psbt","serialize","encode","decode","validate"],"author":{"name":"Christopher Scott"},"license":"CC-BY-1.0","repository":{"type":"git","url":"https://github.com/cmdruid/tapscript.git"},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"devDependencies":{"@cmdcode/buff-utils":"^1.7.6","@cmdcode/crypto-utils":"^1.10.1","@cmdcode/keylink":"^1.4.3","@noble/curves":"^0.9.1","@rollup/plugin-commonjs":"^23.0.2","@rollup/plugin-node-resolve":"^15.0.1","@rollup/plugin-terser":"^0.4.0","@rollup/plugin-typescript":"^9.0.2","@types/node":"^18.14.0","@types/tape":"^4.13.2","@typescript-eslint/eslint-plugin":"^5.48.0","@typescript-eslint/parser":"^5.59.9","eslint":"^8.31.0","eslint-config-standard-with-typescript":"^26.0.0","eslint-plugin-import":"^2.26.0","eslint-plugin-n":"^15.6.0","eslint-plugin-promise":"^6.1.1","nyc":"^15.1.0","rollup":"^3.2.3","tap-spec":"^5.0.0","tape":"^5.6.1","ts-node":"^10.9.1","typescript":"^4.9.4","zod":"^3.20.6"},"dependencies":{"@0xflick/crypto-utils":"^1.10.3-0xflick.0"},"licenseText":"Creative Commons Legal Code\n\nCC0 1.0 Universal\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE\n    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN\n    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS\n    INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES\n    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS\n    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM\n    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED\n    HEREUNDER.\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator\nand subsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for\nthe purpose of contributing to a commons of creative, cultural and\nscientific works (\"Commons\") that the public can reliably and without fear\nof later claims of infringement build upon, modify, incorporate in other\nworks, reuse and redistribute as freely as possible in any form whatsoever\nand for any purposes, including without limitation commercial purposes.\nThese owners may contribute to the Commons to promote the ideal of a free\nculture and the further production of creative, cultural and scientific\nworks, or to gain reputation or greater distribution for their Work in\npart through the use and efforts of others.\n\nFor these and/or other purposes and motivations, and without any\nexpectation of additional consideration or compensation, the person\nassociating CC0 with a Work (the \"Affirmer\"), to the extent that he or she\nis an owner of Copyright and Related Rights in the Work, voluntarily\nelects to apply CC0 to the Work and publicly distribute the Work under its\nterms, with knowledge of his or her Copyright and Related Rights in the\nWork and the meaning and intended legal effect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not\nlimited to, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display,\n     communicate, and translate a Work;\n ii. moral rights retained by the original author(s) and/or performer(s);\niii. publicity and privacy rights pertaining to a person's image or\n     likeness depicted in a Work;\n iv. rights protecting against unfair competition in regards to a Work,\n     subject to the limitations in paragraph 4(a), below;\n  v. rights protecting the extraction, dissemination, use and reuse of data\n     in a Work;\n vi. database rights (such as those arising under Directive 96/9/EC of the\n     European Parliament and of the Council of 11 March 1996 on the legal\n     protection of databases, and under any national implementation\n     thereof, including any amended or successor version of such\n     directive); and\nvii. other similar, equivalent or corresponding rights throughout the\n     world based on applicable law or treaty, and any national\n     implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention\nof, applicable law, Affirmer hereby overtly, fully, permanently,\nirrevocably and unconditionally waives, abandons, and surrenders all of\nAffirmer's Copyright and Related Rights and associated claims and causes\nof action, whether now known or unknown (including existing as well as\nfuture claims and causes of action), in the Work (i) in all territories\nworldwide, (ii) for the maximum duration provided by applicable law or\ntreaty (including future time extensions), (iii) in any current or future\nmedium and for any number of copies, and (iv) for any purpose whatsoever,\nincluding without limitation commercial, advertising or promotional\npurposes (the \"Waiver\"). Affirmer makes the Waiver for the benefit of each\nmember of the public at large and to the detriment of Affirmer's heirs and\nsuccessors, fully intending that such Waiver shall not be subject to\nrevocation, rescission, cancellation, termination, or any other legal or\nequitable action to disrupt the quiet enjoyment of the Work by the public\nas contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason\nbe judged legally invalid or ineffective under applicable law, then the\nWaiver shall be preserved to the maximum extent permitted taking into\naccount Affirmer's express Statement of Purpose. In addition, to the\nextent the Waiver is so judged Affirmer hereby grants to each affected\nperson a royalty-free, non transferable, non sublicensable, non exclusive,\nirrevocable and unconditional license to exercise Affirmer's Copyright and\nRelated Rights in the Work (i) in all territories worldwide, (ii) for the\nmaximum duration provided by applicable law or treaty (including future\ntime extensions), (iii) in any current or future medium and for any number\nof copies, and (iv) for any purpose whatsoever, including without\nlimitation commercial, advertising or promotional purposes (the\n\"License\"). The License shall be deemed effective as of the date CC0 was\napplied by Affirmer to the Work. Should any part of the License for any\nreason be judged legally invalid or ineffective under applicable law, such\npartial invalidity or ineffectiveness shall not invalidate the remainder\nof the License, and in such case Affirmer hereby affirms that he or she\nwill not (i) exercise any of his or her remaining Copyright and Related\nRights in the Work or (ii) assert any associated claims and causes of\naction with respect to the Work, in either case contrary to Affirmer's\nexpress Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n a. No trademark or patent rights held by Affirmer are waived, abandoned,\n    surrendered, licensed or otherwise affected by this document.\n b. Affirmer offers the Work as-is and makes no representations or\n    warranties of any kind concerning the Work, express, implied,\n    statutory or otherwise, including without limitation warranties of\n    title, merchantability, fitness for a particular purpose, non\n    infringement, or the absence of latent or other defects, accuracy, or\n    the present or absence of errors, whether or not discoverable, all to\n    the greatest extent permissible under applicable law.\n c. Affirmer disclaims responsibility for clearing rights of other persons\n    that may apply to the Work or any use thereof, including without\n    limitation any person's Copyright and Related Rights in the Work.\n    Further, Affirmer disclaims responsibility for obtaining any necessary\n    consents, permissions or other rights required for any use of the\n    Work.\n d. Affirmer understands and acknowledges that Creative Commons is not a\n    party to this document and has no duty or obligation with respect to\n    this CC0 or use of the Work.\n","_id":"@0xflick/tapscript@1.2.11-0xflick.0","dist":{"shasum":"b33caf65e457d58c8ebdb542ba522b864e3d4674","integrity":"sha512-Hcl5I3Us3eFn9vsGHCnYrzQYHtXLniOHFLEQxwmiVyQiXdtLqpOXMSKF2CityH6CX4s6ngkgXoR0Z65kaTGwuw==","tarball":"https://registry.npmjs.org/@0xflick/tapscript/-/tapscript-1.2.11-0xflick.0.tgz","fileCount":118,"unpackedSize":109472,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA5OyM02KsAjC4PtmHuqm7n0mwf4Xxj8cJ+1d2K0C03OAiBNc+gixsElNG7pMcAlqo2QDsykp5CtOL1jMG1BvBJ1uw=="}]},"_npmUser":{"name":"0xflick","email":"cmdrnft@protonmail.com"},"directories":{},"maintainers":[{"name":"0xflick","email":"cmdrnft@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tapscript_1.2.11-0xflick.0_1688610788664_0.4633449359752888"},"_hasShrinkwrap":false},"1.2.11-0xflick.1":{"name":"@0xflick/tapscript","version":"1.2.11-0xflick.1","description":"A basic library for working with Tapscript, signatures and Bitcoin transactions.","type":"module","main":"./dist/main.cjs","unpkg":"./dist/bundle.min.js","types":"./dist/types/index.d.ts","exports":{"import":"./dist/module.mjs","require":"./dist/main.cjs","types":"./dist/types/index.d.ts"},"scripts":{"build":"rollup -c rollup.config.ts --configPlugin typescript","clean":"rm -rf dist/* coverage .nyc_output","start":"node --trace-deprecation --no-warnings --loader ts-node/esm","scratch":"yarn start test/scratch.ts","lint":"eslint . --ext .ts","fix":"eslint --fix . --ext .ts","tape":"yarn start test/tape.ts","test":"nyc --reporter=lcov --require ts-node/register yarn tape | tap-spec; nyc report ---reporter=text","types":"tsc","release":"yarn test && yarn clean && yarn types && yarn lint && yarn build"},"keywords":["bitcoin","transaction","psbt","serialize","encode","decode","validate"],"author":{"name":"Christopher Scott"},"license":"CC-BY-1.0","repository":{"type":"git","url":"git+https://github.com/cmdruid/tapscript.git"},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"devDependencies":{"@cmdcode/buff-utils":"^1.7.6","@cmdcode/crypto-utils":"^1.10.1","@cmdcode/keylink":"^1.4.3","@noble/curves":"^0.9.1","@rollup/plugin-commonjs":"^23.0.2","@rollup/plugin-node-resolve":"^15.0.1","@rollup/plugin-terser":"^0.4.0","@rollup/plugin-typescript":"^9.0.2","@types/node":"^18.14.0","@types/tape":"^4.13.2","@typescript-eslint/eslint-plugin":"^5.48.0","@typescript-eslint/parser":"^5.59.9","eslint":"^8.31.0","eslint-config-standard-with-typescript":"^26.0.0","eslint-plugin-import":"^2.26.0","eslint-plugin-n":"^15.6.0","eslint-plugin-promise":"^6.1.1","nyc":"^15.1.0","rollup":"^3.2.3","tap-spec":"^5.0.0","tape":"^5.6.1","ts-node":"^10.9.1","typescript":"^4.9.4","zod":"^3.20.6"},"dependencies":{"@0xflick/crypto-utils":"^1.10.3-0xflick.0"},"gitHead":"62314ee0d4ef21ce0441bdd9efe6c443d538e8cf","bugs":{"url":"https://github.com/cmdruid/tapscript/issues"},"homepage":"https://github.com/cmdruid/tapscript#readme","_id":"@0xflick/tapscript@1.2.11-0xflick.1","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-gtyTyMrM0H9TxV+zEAglTln79/861NBlBTN+Qhd8pUQJwUBZV32Nx0ckSvDftUsGkVobTFQ0uVnDf2EBg5yq8A==","shasum":"5b54315722d5877cf597a81568c6a2a491e9877b","tarball":"https://registry.npmjs.org/@0xflick/tapscript/-/tapscript-1.2.11-0xflick.1.tgz","fileCount":109,"unpackedSize":5562438,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICzHWTPNTM/ocX0eYjLr5qoYgo7AiFVtQA55Wkz04lL+AiEA4NNHK3tuogGkyMYcH+pCvp4nU9pCGUBSJYUEGOxztF0="}]},"_npmUser":{"name":"0xflick","email":"cmdrnft@protonmail.com"},"directories":{},"maintainers":[{"name":"0xflick","email":"cmdrnft@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tapscript_1.2.11-0xflick.1_1688613300419_0.2562573263630725"},"_hasShrinkwrap":false},"2.0.0":{"name":"@0xflick/tapscript","version":"2.0.0","description":"A basic library for working with Tapscript, signatures and Bitcoin transactions.","type":"module","main":"./dist/main.cjs","unpkg":"./dist/bundle.min.js","types":"./dist/types/index.d.ts","exports":{"import":"./dist/module.mjs","require":"./dist/main.cjs","types":"./dist/types/index.d.ts"},"scripts":{"build":"rollup -c rollup.config.ts --configPlugin typescript","clean":"rm -rf dist/* coverage .nyc_output","start":"node --trace-deprecation --no-warnings --loader ts-node/esm","scratch":"yarn start test/scratch.ts","lint":"eslint . --ext .ts","fix":"eslint --fix . --ext .ts","tape":"yarn start test/tape.ts","test":"nyc --reporter=lcov --require ts-node/register yarn tape | tap-spec; nyc report ---reporter=text","types":"tsc","release":"yarn test && yarn clean && yarn types && yarn lint && yarn build"},"keywords":["bitcoin","transaction","psbt","serialize","encode","decode","validate"],"author":{"name":"Christopher Scott"},"license":"CC-BY-1.0","repository":{"type":"git","url":"https://github.com/cmdruid/tapscript.git"},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"devDependencies":{"@cmdcode/buff-utils":"^1.7.6","@cmdcode/crypto-utils":"^1.10.1","@cmdcode/keylink":"^1.4.3","@noble/curves":"^0.9.1","@rollup/plugin-commonjs":"^23.0.2","@rollup/plugin-node-resolve":"^15.0.1","@rollup/plugin-terser":"^0.4.0","@rollup/plugin-typescript":"^9.0.2","@types/node":"^18.14.0","@types/tape":"^4.13.2","@typescript-eslint/eslint-plugin":"^5.48.0","@typescript-eslint/parser":"^5.59.9","eslint":"^8.31.0","eslint-config-standard-with-typescript":"^26.0.0","eslint-plugin-import":"^2.26.0","eslint-plugin-n":"^15.6.0","eslint-plugin-promise":"^6.1.1","nyc":"^15.1.0","rollup":"^3.2.3","tap-spec":"^5.0.0","tape":"^5.6.1","ts-node":"^10.9.1","typescript":"^4.9.4","zod":"^3.20.6"},"dependencies":{"@0xflick/crypto-utils":"^1.10.3-0xflick.0"},"licenseText":"Creative Commons Legal Code\n\nCC0 1.0 Universal\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE\n    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN\n    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS\n    INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES\n    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS\n    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM\n    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED\n    HEREUNDER.\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator\nand subsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for\nthe purpose of contributing to a commons of creative, cultural and\nscientific works (\"Commons\") that the public can reliably and without fear\nof later claims of infringement build upon, modify, incorporate in other\nworks, reuse and redistribute as freely as possible in any form whatsoever\nand for any purposes, including without limitation commercial purposes.\nThese owners may contribute to the Commons to promote the ideal of a free\nculture and the further production of creative, cultural and scientific\nworks, or to gain reputation or greater distribution for their Work in\npart through the use and efforts of others.\n\nFor these and/or other purposes and motivations, and without any\nexpectation of additional consideration or compensation, the person\nassociating CC0 with a Work (the \"Affirmer\"), to the extent that he or she\nis an owner of Copyright and Related Rights in the Work, voluntarily\nelects to apply CC0 to the Work and publicly distribute the Work under its\nterms, with knowledge of his or her Copyright and Related Rights in the\nWork and the meaning and intended legal effect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not\nlimited to, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display,\n     communicate, and translate a Work;\n ii. moral rights retained by the original author(s) and/or performer(s);\niii. publicity and privacy rights pertaining to a person's image or\n     likeness depicted in a Work;\n iv. rights protecting against unfair competition in regards to a Work,\n     subject to the limitations in paragraph 4(a), below;\n  v. rights protecting the extraction, dissemination, use and reuse of data\n     in a Work;\n vi. database rights (such as those arising under Directive 96/9/EC of the\n     European Parliament and of the Council of 11 March 1996 on the legal\n     protection of databases, and under any national implementation\n     thereof, including any amended or successor version of such\n     directive); and\nvii. other similar, equivalent or corresponding rights throughout the\n     world based on applicable law or treaty, and any national\n     implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention\nof, applicable law, Affirmer hereby overtly, fully, permanently,\nirrevocably and unconditionally waives, abandons, and surrenders all of\nAffirmer's Copyright and Related Rights and associated claims and causes\nof action, whether now known or unknown (including existing as well as\nfuture claims and causes of action), in the Work (i) in all territories\nworldwide, (ii) for the maximum duration provided by applicable law or\ntreaty (including future time extensions), (iii) in any current or future\nmedium and for any number of copies, and (iv) for any purpose whatsoever,\nincluding without limitation commercial, advertising or promotional\npurposes (the \"Waiver\"). Affirmer makes the Waiver for the benefit of each\nmember of the public at large and to the detriment of Affirmer's heirs and\nsuccessors, fully intending that such Waiver shall not be subject to\nrevocation, rescission, cancellation, termination, or any other legal or\nequitable action to disrupt the quiet enjoyment of the Work by the public\nas contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason\nbe judged legally invalid or ineffective under applicable law, then the\nWaiver shall be preserved to the maximum extent permitted taking into\naccount Affirmer's express Statement of Purpose. In addition, to the\nextent the Waiver is so judged Affirmer hereby grants to each affected\nperson a royalty-free, non transferable, non sublicensable, non exclusive,\nirrevocable and unconditional license to exercise Affirmer's Copyright and\nRelated Rights in the Work (i) in all territories worldwide, (ii) for the\nmaximum duration provided by applicable law or treaty (including future\ntime extensions), (iii) in any current or future medium and for any number\nof copies, and (iv) for any purpose whatsoever, including without\nlimitation commercial, advertising or promotional purposes (the\n\"License\"). The License shall be deemed effective as of the date CC0 was\napplied by Affirmer to the Work. Should any part of the License for any\nreason be judged legally invalid or ineffective under applicable law, such\npartial invalidity or ineffectiveness shall not invalidate the remainder\nof the License, and in such case Affirmer hereby affirms that he or she\nwill not (i) exercise any of his or her remaining Copyright and Related\nRights in the Work or (ii) assert any associated claims and causes of\naction with respect to the Work, in either case contrary to Affirmer's\nexpress Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n a. No trademark or patent rights held by Affirmer are waived, abandoned,\n    surrendered, licensed or otherwise affected by this document.\n b. Affirmer offers the Work as-is and makes no representations or\n    warranties of any kind concerning the Work, express, implied,\n    statutory or otherwise, including without limitation warranties of\n    title, merchantability, fitness for a particular purpose, non\n    infringement, or the absence of latent or other defects, accuracy, or\n    the present or absence of errors, whether or not discoverable, all to\n    the greatest extent permissible under applicable law.\n c. Affirmer disclaims responsibility for clearing rights of other persons\n    that may apply to the Work or any use thereof, including without\n    limitation any person's Copyright and Related Rights in the Work.\n    Further, Affirmer disclaims responsibility for obtaining any necessary\n    consents, permissions or other rights required for any use of the\n    Work.\n d. Affirmer understands and acknowledges that Creative Commons is not a\n    party to this document and has no duty or obligation with respect to\n    this CC0 or use of the Work.\n","_id":"@0xflick/tapscript@2.0.0","dist":{"shasum":"889361a6a3071ff2d5681b7451196ae5aac652f8","integrity":"sha512-2Ubo05J8yh6Pa8x0hKF0aIahd7CKoQcNiDgMHROK9rB6xuBruQ0AqJ12pHP/L44530zMYbRHY6ok8Hh+JvCBBA==","tarball":"https://registry.npmjs.org/@0xflick/tapscript/-/tapscript-2.0.0.tgz","fileCount":124,"unpackedSize":5562520,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxz+m+xV0EC3uz6bnT+a3I+iqTuA19oTJ22TFc8tlgKgIgRSG0mUIB8h2ZJuA+Ldi4dl6OuI4MqkN5A/nRuqjTVg8="}]},"_npmUser":{"name":"0xflick","email":"cmdrnft@protonmail.com"},"directories":{},"maintainers":[{"name":"0xflick","email":"cmdrnft@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tapscript_2.0.0_1689482865613_0.9362651626663192"},"_hasShrinkwrap":false},"2.0.1":{"name":"@0xflick/tapscript","version":"2.0.1","description":"A basic library for working with Tapscript, signatures and Bitcoin transactions.","type":"module","main":"./dist/main.cjs","unpkg":"./dist/bundle.min.js","types":"./dist/types/index.d.ts","exports":{"import":"./dist/module.mjs","require":"./dist/main.cjs","types":"./dist/types/index.d.ts"},"scripts":{"build":"rollup -c rollup.config.ts --configPlugin typescript","clean":"rm -rf dist/* coverage .nyc_output","start":"node --trace-deprecation --no-warnings --loader ts-node/esm","scratch":"yarn start test/scratch.ts","lint":"eslint . --ext .ts","fix":"eslint --fix . --ext .ts","tape":"yarn start test/tape.ts","test":"nyc --reporter=lcov --require ts-node/register yarn tape | tap-spec; nyc report ---reporter=text","types":"tsc","release":"yarn test && yarn clean && yarn types && yarn lint && yarn build"},"keywords":["bitcoin","transaction","psbt","serialize","encode","decode","validate"],"author":{"name":"Christopher Scott"},"license":"CC-BY-1.0","repository":{"type":"git","url":"https://github.com/cmdruid/tapscript.git"},"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"devDependencies":{"@cmdcode/buff-utils":"^1.7.6","@cmdcode/crypto-utils":"^1.10.1","@cmdcode/keylink":"^1.4.3","@noble/curves":"^0.9.1","@rollup/plugin-commonjs":"^23.0.2","@rollup/plugin-node-resolve":"^15.0.1","@rollup/plugin-terser":"^0.4.0","@rollup/plugin-typescript":"^9.0.2","@types/node":"^18.14.0","@types/tape":"^4.13.2","@typescript-eslint/eslint-plugin":"^5.48.0","@typescript-eslint/parser":"^5.59.9","eslint":"^8.31.0","eslint-config-standard-with-typescript":"^26.0.0","eslint-plugin-import":"^2.26.0","eslint-plugin-n":"^15.6.0","eslint-plugin-promise":"^6.1.1","nyc":"^15.1.0","rollup":"^3.2.3","tap-spec":"^5.0.0","tape":"^5.6.1","ts-node":"^10.9.1","typescript":"^4.9.4","zod":"^3.20.6"},"dependencies":{"@0xflick/crypto-utils":"^1.10.3-0xflick.0"},"licenseText":"Creative Commons Legal Code\n\nCC0 1.0 Universal\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE\n    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN\n    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS\n    INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES\n    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS\n    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM\n    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED\n    HEREUNDER.\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator\nand subsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for\nthe purpose of contributing to a commons of creative, cultural and\nscientific works (\"Commons\") that the public can reliably and without fear\nof later claims of infringement build upon, modify, incorporate in other\nworks, reuse and redistribute as freely as possible in any form whatsoever\nand for any purposes, including without limitation commercial purposes.\nThese owners may contribute to the Commons to promote the ideal of a free\nculture and the further production of creative, cultural and scientific\nworks, or to gain reputation or greater distribution for their Work in\npart through the use and efforts of others.\n\nFor these and/or other purposes and motivations, and without any\nexpectation of additional consideration or compensation, the person\nassociating CC0 with a Work (the \"Affirmer\"), to the extent that he or she\nis an owner of Copyright and Related Rights in the Work, voluntarily\nelects to apply CC0 to the Work and publicly distribute the Work under its\nterms, with knowledge of his or her Copyright and Related Rights in the\nWork and the meaning and intended legal effect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not\nlimited to, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display,\n     communicate, and translate a Work;\n ii. moral rights retained by the original author(s) and/or performer(s);\niii. publicity and privacy rights pertaining to a person's image or\n     likeness depicted in a Work;\n iv. rights protecting against unfair competition in regards to a Work,\n     subject to the limitations in paragraph 4(a), below;\n  v. rights protecting the extraction, dissemination, use and reuse of data\n     in a Work;\n vi. database rights (such as those arising under Directive 96/9/EC of the\n     European Parliament and of the Council of 11 March 1996 on the legal\n     protection of databases, and under any national implementation\n     thereof, including any amended or successor version of such\n     directive); and\nvii. other similar, equivalent or corresponding rights throughout the\n     world based on applicable law or treaty, and any national\n     implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention\nof, applicable law, Affirmer hereby overtly, fully, permanently,\nirrevocably and unconditionally waives, abandons, and surrenders all of\nAffirmer's Copyright and Related Rights and associated claims and causes\nof action, whether now known or unknown (including existing as well as\nfuture claims and causes of action), in the Work (i) in all territories\nworldwide, (ii) for the maximum duration provided by applicable law or\ntreaty (including future time extensions), (iii) in any current or future\nmedium and for any number of copies, and (iv) for any purpose whatsoever,\nincluding without limitation commercial, advertising or promotional\npurposes (the \"Waiver\"). Affirmer makes the Waiver for the benefit of each\nmember of the public at large and to the detriment of Affirmer's heirs and\nsuccessors, fully intending that such Waiver shall not be subject to\nrevocation, rescission, cancellation, termination, or any other legal or\nequitable action to disrupt the quiet enjoyment of the Work by the public\nas contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason\nbe judged legally invalid or ineffective under applicable law, then the\nWaiver shall be preserved to the maximum extent permitted taking into\naccount Affirmer's express Statement of Purpose. In addition, to the\nextent the Waiver is so judged Affirmer hereby grants to each affected\nperson a royalty-free, non transferable, non sublicensable, non exclusive,\nirrevocable and unconditional license to exercise Affirmer's Copyright and\nRelated Rights in the Work (i) in all territories worldwide, (ii) for the\nmaximum duration provided by applicable law or treaty (including future\ntime extensions), (iii) in any current or future medium and for any number\nof copies, and (iv) for any purpose whatsoever, including without\nlimitation commercial, advertising or promotional purposes (the\n\"License\"). The License shall be deemed effective as of the date CC0 was\napplied by Affirmer to the Work. Should any part of the License for any\nreason be judged legally invalid or ineffective under applicable law, such\npartial invalidity or ineffectiveness shall not invalidate the remainder\nof the License, and in such case Affirmer hereby affirms that he or she\nwill not (i) exercise any of his or her remaining Copyright and Related\nRights in the Work or (ii) assert any associated claims and causes of\naction with respect to the Work, in either case contrary to Affirmer's\nexpress Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n a. No trademark or patent rights held by Affirmer are waived, abandoned,\n    surrendered, licensed or otherwise affected by this document.\n b. Affirmer offers the Work as-is and makes no representations or\n    warranties of any kind concerning the Work, express, implied,\n    statutory or otherwise, including without limitation warranties of\n    title, merchantability, fitness for a particular purpose, non\n    infringement, or the absence of latent or other defects, accuracy, or\n    the present or absence of errors, whether or not discoverable, all to\n    the greatest extent permissible under applicable law.\n c. Affirmer disclaims responsibility for clearing rights of other persons\n    that may apply to the Work or any use thereof, including without\n    limitation any person's Copyright and Related Rights in the Work.\n    Further, Affirmer disclaims responsibility for obtaining any necessary\n    consents, permissions or other rights required for any use of the\n    Work.\n d. Affirmer understands and acknowledges that Creative Commons is not a\n    party to this document and has no duty or obligation with respect to\n    this CC0 or use of the Work.\n","_id":"@0xflick/tapscript@2.0.1","dist":{"shasum":"c1e580d3fdd2bb2587cf2167dc699b8e3f72dcfa","integrity":"sha512-z4ixc71HozqY9mJ5VcHxPau8wfpTa5/0/kT012q0pc47XGlxPrizllLrDwkejkZ4lNp9qNzKP+nSgTWIPy4gIw==","tarball":"https://registry.npmjs.org/@0xflick/tapscript/-/tapscript-2.0.1.tgz","fileCount":124,"unpackedSize":5562629,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBMxTT8j/15tNfHUo9VqjUqj+5xKhqo9+StYQ/9yEtqVAiAqnFWhRRO/Zx1z09TWzI0ZKZPxR8FyrMCw8U9OI+LtlQ=="}]},"_npmUser":{"name":"0xflick","email":"cmdrnft@protonmail.com"},"directories":{},"maintainers":[{"name":"0xflick","email":"cmdrnft@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/tapscript_2.0.1_1689483353819_0.629915264683667"},"_hasShrinkwrap":false}},"time":{"created":"2023-07-06T02:33:08.601Z","1.2.11-0xflick.0":"2023-07-06T02:33:08.879Z","modified":"2023-07-16T04:55:54.237Z","1.2.11-0xflick.1":"2023-07-06T03:15:00.748Z","2.0.0":"2023-07-16T04:47:45.853Z","2.0.1":"2023-07-16T04:55:54.059Z"},"maintainers":[{"name":"0xflick","email":"cmdrnft@protonmail.com"}],"description":"A basic library for working with Tapscript, signatures and Bitcoin transactions.","keywords":["bitcoin","transaction","psbt","serialize","encode","decode","validate"],"repository":{"type":"git","url":"https://github.com/cmdruid/tapscript.git"},"author":{"name":"Christopher Scott"},"license":"CC-BY-1.0","readme":"# Tapscript\n\nA basic library for working with Taproot, Schnorr Signatures, and Bitcoin transactions.\n\n> Note: For nodejs users, please upgrade to version 19+ for globalThis support.\n\n## Introduction\n\nTapscript uses the latest feature upgrade to Bitcoin called Taproot. If you are new to Bitcoin or the Taproot upgrade, please continue reading for a brief overview of how it works. This library will be easier to follow if you know what taproot is doing under the hood.\n\nIf you already have a good understanding of Bitcoin and Taproot, feel free to skip ahead by clicking [here](#tool-index).\n\n## What is Taproot?\n\nBitcoin uses a simple scripting language (called Bitcoin Script) that allows you to lock up coins into a contract. These contracts are published to the blockchain and enforced by all nodes in the network.\n\nIn order to settle a contract (and claim its coins), you are required to publish the *entire* contract, including parts that are not relevant to the settlement. This is expensive and wasteful, plus it leaks information that could have otherwise been kept private.\n\nTaproot is a new way to publish these contracts to the blockchain that fixes the above concerns. It allows you to settle contracts by publishing only the portion of the contract that is relevant. This means smaller transactions, cheaper fees, and better privacy guarantees for the contract as a whole.\n\nTaproot also comes with many other benefits, including:\n\n * It drastically simplifies the flow and logic of writing a contract.\n * You can create large, complex contracts that only need a small transaction to settle.\n * Commitments to data and other arbitrary things can be thrown into your contract for free.\n * The new schnorr-based signature format lets you do some crazy cool stuff (BIP340).\n\nRead more about the Taproot upgrade in 2019 [here](https://cointelegraph.com/bitcoin-for-beginners/a-beginners-guide-to-the-bitcoin-taproot-upgrade).\n\n## How does Taproot work?\n\nTaproot uses a simple trick involving something called a \"merkle tree\".\n\n```\n                hash(ab, cd)                  <- Final hash    (the root)\n              /             \\                \n      hash(a, b)             hash(c, d)       <- Combined hash (the branches)\n     /          \\           /          \\    \n    hash(a) hash(b)        hash(c) hash(d)    <- Initial hash  (the leaves)\n[ script(a), script(b), script(c), script(d) ]  \n```\n\nA merkle tree is simply a list of data that is reduced down into a single hash value. We do this by hashing values together in pairs of two, repeatedly, until we are naturally left with one value (the root).\n\nThe great thing about merkle trees is that you can use the root hash to prove that a piece of data (such as a script) was included somewhere in the tree, without having to reveal the entire tree.\n\nFor example, to prove that script(a) exists in the tree, we simply provide hash(b) and hash(c, d). This is all the information we need to recreate the root hash(ab, cd). We do not reveal any of the other scripts.\n\nThis allows us to break up a contract into many scripts, then lock coins to the root hash of our combined scripts. To redeem coins, we simply need to provide one of the scripts, plus a 'path' of hashes that lead us to the root hash of the tree.\n\n## About Key Tweaking\n\nAnother clever trick that Taproot uses, is something called \"key tweaking\".\n\nIn order to create a pair of keys used for signatures, we start with a secret number, or \"key\". We then multiply this key by a very large prime number, called a \"generator\" (G). This process is done in a way that is computationally impossible to reverse without knowing the secret. The resulting number then becomes our public key.\n\n```\nseckey * G => pubkey\n```\n\nWe use a special set of numbers when making key-pairs, so that some arithmetic still works between the keys, without breaking their secret relationship with G. This is how we produce signatures and proofs.\n\n```\nseckey +    randomkey    +    msg    = signature      <= Does not reveal seckey.\npubkey + (randomkey * G) + (msg * G) = signature * G  <= Proves that seckey was used.\n```\n\nKey tweaking is just an extention of this. We use a piece of data to \"tweak\" both keys in our key-pair, then use the modified keys to sign and verify transactions.\n\n```\nseckey +    tweak    = tweaked_seckey\npubkey + (tweak * G) = tweaked_pubkey\n```\n\nLater, we can choose to reveal the original public key and tweak, as proof that both were used to construct the modified key. Or we can simply choose to sign using the modified key, and not reveal anything!\n\nTaproot uses key tweaking in order to lock coins to our pubkey + root of our tree. This provides us with two paths for spending coins:\n\n * Using the tweaked pubkey (without revealing anything).\n * Using the interal pubkey + script + proof.\n\n> Note: the \"proof\" is the path of hashes we described earlier, which is needed to recompute the root hash.\n\nIf you want to eliminate the key-spending path (so that a script *must* be used to redeem funds), you can replace the pubkey with a random number. However, it is best to use a number that everyone can verify has an unknown secret key. One example of such a number is the following:\n\n```js\n// BIP0341 specifies using the following pubkey value for script-only contracts.\n// It is created by hashing the DER encoded coordinates of secp256k1 base point G:\n'0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0'\n// Since this pubkey was generated using a hash function, there is no feasible way \n// to compute what the matching private key would be.\n```\n\n## Tool Index\n\nThis library provides a suite of tools for working with scripts, taproot, key tweaking, signatures and transactions. Use the links below to jump to the documentation for a certain tool.\n\n[**Address Tool**](#address-tool)  \nEncode, decode, check, and convert various address types.  \n[**Script Tool**](#script-tool)  \nEncode scripts into hex, or decode into a script array.  \n[**Signer Tool**](#signer-tool)  \nProduce signatures and validate signed transactions.  \n[**Tap Tool**](#tap-tool)  \nBuild, tweak, and validate trees of data / scripts.  \n[**Tx Tool**](#tx-tool)  \nEncode transactions into hex, or decode into a JSON object.\n\n### About Buff\n\nThis library makes heavy use of the [Buff](https://github.com/cmdruid/buff-utils) tool for converting between data types. Buff is an extention of the Uint8Array type, so all Buff objects can naturally be treated as Uint8Array objects. Buff objects however incude an extensive API for converting into different types (*for ex: buff.hex for hex strings*). Please check the above link for more information on how to use Buff.\n\n### Import\n\nExample import into a browser-based project:\n```html\n<script src=\"https://unpkg.com/@cmdcode/tapscript\"></script>\n<script> const { Address, Script, Signer, Tap, Tx } = window.tapscript </script>\n```\nExample import into a commonjs project:\n```ts\nconst { Address, Script, Signer, Tap, Tx } = require('@cmdcode/tapscript')\n```\nExample import into an ES module project:\n```ts\nimport { Address, Script, Signer, Tap, Tx } from '@cmdcode/tapscript'\n```\n\n### Address Tool\n\nThis tool allows you to encode, decode, check, an convert various address types.\n\n```ts\nAddress = {\n  // Work with Pay-to-Pubkey-Hash addresses (Base58 encoded).\n  p2pkh  : => AddressTool,\n  // Work with Pay-to-Script-Hash addresses (Base58 encoded).\n  p2sh   : => AddressTool,\n  // Work with Pay-to-Witness PubKey-Hash addresses (Bech32 encoded).\n  p2wpkh : => AddressTool,\n  // Work with Pay-to-Witness Script-Hash addresses (Bech32 encoded).\n  p2wsh  : => AddressTool,\n  // Work with Pay-to-Taproot addresses (Bech32m encoded).\n  p2tr   : => AddressTool,\n  // Decode any address format into a detailed object.\n  decode   : (address : string) => AddressData,\n  // Convert any address into its scriptPubKey format.\n  toScriptPubKey : (address : string) => Buff\n}\n\ninterface AddressTool {\n  // Check if an address is valid.\n  check  : (address : string, network ?: Networks) => boolean\n  // Decode an address into a pubkey hash or script hash.\n  decode : (address : string, network ?: Networks) => Buff\n  // Convert a key or script into the proper hash.\n  hash   : (input : Bytes | ScriptData) => Buff\n  // Encode a pubkey hash or script hash into an address.\n  encode : (input : Bytes,  network ?: Networks) => string\n  // Return the scriptPubKey script for an address type.\n  scriptPubKey : (input : string) => string[]\n  // Return an address based on a public key (PKH type addresses only).\n  fromPubKey : (pubkey : Bytes, network ?: Networks) => string\n  // Return an address based on a script key (SH type addresses only).\n  fromScript : (script : ScriptData, network ?: Networks) => string\n}\n\ninterface AddressData {\n  data    : Buff\n  network : Networks\n  prefix  : string\n  script  : string[]\n  type    : keyof AddressTools\n}\n\ntype Networks = 'main' | 'testnet' | 'signet' | 'regtest'\n```\n\n#### Examples\n\nExample of using the main `Address` API.\n\n```ts\nconst address = 'bcrt1q738hdjlatdx9xmg3679kwq9cwd7fa2c84my9zk'\n// You can decode any address, extract data, or convert to a scriptPubKey format.\nconst decoded = Address.decode(address)\n// Example of the decoded data object.\n{ \n  prefix  : 'bcrt1q', \n  type    : 'p2w', \n  network : 'regtest', \n  data    : 'f44f76cbfd5b4c536d11d78b6700b8737c9eab07',\n  script  : [ 'OP_0', 'f44f76cbfd5b4c536d11d78b6700b8737c9eab07' ]\n}\n// You can also quickly convert between address and scriptPubKey formats.\nconst bytes = Address.toScriptPubKey(address)\n// Bytes: 0014f44f76cbfd5b4c536d11d78b6700b8737c9eab07\nconst address = Address.fromScriptPubKey(scriptPubKey)\n// Address : bcrt1q738hdjlatdx9xmg3679kwq9cwd7fa2c84my9zk\n```\n\nExample of using the AddressTool API for a given address type.\n\n```ts\n// Example 33-byte public key.\nconst pubkey  = '03d5af2a3e89cb72ff9ca1b36091ca46e4d4399abc5574b13d3e56bca6c0784679'\n// You can encode / decode / convert keys and script hashes.\nconst address = Address.p2wpkh.fromPubKey(pubkey, 'regtest')\n// Address: bcrt1q738hdjlatdx9xmg3679kwq9cwd7fa2c84my9zk\nconst address = Address.p2wpkh.encode(keyhash, 'regtest')\n// Address: bcrt1q738hdjlatdx9xmg3679kwq9cwd7fa2c84my9zk\nconst bytes   = Address.p2wpkh.decode(address)\n// KeyHash: f44f76cbfd5b4c536d11d78b6700b8737c9eab07\nconst script  = Address.p2wpkh.scriptPubKey(bytes)\n// script: script: [ 'OP_0', 'f44f76cbfd5b4c536d11d78b6700b8737c9eab07' ]\n```\n\n### Script Tool\n\nThis tool helps with parsing / serializing scripts.\n\n```ts\nScript = {\n  // Encode a JSON formatted script into hex.\n  encode : (script : ScriptData, varint = true) => string,\n  // Decode a hex formatted script into JSON.\n  decode : (script : string, varint = false)    => ScriptData\n  // Normalize script / data to a particular format:\n  fmt : {\n    // Convert script to opcodes / hex data (asm format).\n    toAsm()   => string[]  (asm format).\n    // Convert script to bytes (script hex).\n    toBytes() => Buff\n     // Convert non-script witness data to bytes.\n    toParam() => Buff  \n  }\n}\n```\n\n### Signer Tool.\n\nThis tool helps with signatures and validation.\n\n```ts\nSigner.taproot = {\n  // Calculate the signature hash for a transaction.\n  hash : (\n    txdata  : TxData | Bytes,\n    index   : number,\n    config  : HashConfig = {}\n  ) => Uint8Array,\n  // Sign a transaction using your *tweaked* private key.\n  sign : (\n    seckey  : Bytes,\n    txdata  : TxData | Bytes,\n    index   : number,\n    config  : HashConfig = {}\n  ) => Uint8Array,\n  // Verify a transaction using the included tapkey (or specify a pubkey).\n  verify : (\n    txdata  : TxData | Bytes,\n    index   : number,\n    config  : HashConfig = {}\n  ) => boolean\n}\n\ninterface HashConfig {\n  extension     ?: Bytes    // Hash and sign using this tapleaf.\n  pubkey        ?: Bytes    // Verify using this pubkey instead of the tapkey.\n  script        ?: Bytes    // Hash and sign using this script (for segwit spends).\n  sigflag       ?: number   // Set the signature type flag.\n  separator_pos ?: number   // If using OP_CODESEPARATOR, specify the latest opcode position.\n  extflag       ?: number   // Set the extention version flag (future use).\n  key_version   ?: number   // Set the key version flag (future use).\n  throws        ?: boolean  // Should throw an exception on failure.\n}\n```\n\n#### Example\n\nExample of a basic pay-to-taproot key spend (similar to pay-to-pubkey):\n\n```ts\n// Sample secret / public key pair.\nconst seckey  = '730fff80e1413068a05b57d6a58261f07551163369787f349438ea38ca80fac6'\nconst pubkey  = '0307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3'\n\n// For key-spends, we need to tweak both the secret key and public key.\nconst [ tseckey ] = Tap.getSecKey(seckey)\nconst [ tpubkey ] = Tap.getPubKey(pubkey)\n\n// Our taproot address is the encoded version of our public tapkey.\nconst address = Address.p2tr.encode(tpubkey, 'regtest')\n\n// NOTE: For the next step, you need to send 100_000 sats to the above address.\n// Make note of the txid of this transaction, plus the index of the output that\n// you are spending.\n\nconst txdata = Tx.create({\n  vin  : [{\n    // The txid of your funding transaction.\n    txid: 'fbde7872cc1aca4bc93ac9a923f14c3355b4216cac3f43b91663ede7a929471b',\n    // The index of the output you are spending.\n    vout: 0,\n    // For Taproot, we need to specify this data when signing.\n    prevout: {\n      // The value of the output we are spending.\n      value: 100000,\n      // This is the script that our taproot address decodes into.\n      scriptPubKey: [ 'OP_1', tpubkey ]\n    },\n  }],\n  vout : [{\n    // We are locking up 99_000 sats (minus 1000 sats for fees.)\n    value: 99000,\n    // We are locking up funds to this address.\n    scriptPubKey: Address.toScriptPubKey('bcrt1q6zpf4gefu4ckuud3pjch563nm7x27u4ruahz3y')\n  }]\n})\n\n// For this example, we are signing for input 0.\n\n// Provide your tweaked secret key with the transaction, \n// plus the index # of the input you are signing for.\nconst sig = Signer.taproot.sign(tseckey, txdata, 0)\n\n// Add your signature to the witness data for that input.\ntxdata.vin[0].witness = [ sig ]\n\n// For verification, provided your \nawait Signer.taproot.verify(txdata, 0, { throws: true })\n\nconsole.log('Your address:', address)\nconsole.log('Your txhex:', Tx.encode(txdata).hex)\n```\n\nYou can find more examples in the main **Examples** section further down.\n\n> Note: There is also an identical `Signer.segwit` tool for signing and validating segwit (BIP0143) transactions. The segwit signer currently does not support the use of OP_CODESEAPRATOR. Any scripts containing this opcode will throw an exception by default.\n\n### Tap Tool\n\n```ts\nTap = {\n  // Returns the tweaked public key (and cblock) for a given tree (and target).\n  getPubKey    : (pubkey : Bytes, config ?: TapConfig)  => TapKey,\n  // Returns the tweaked secret key (and cblock) for a given tree (and target).\n  getSecKey    : (seckey : Bytes, config ?: TapConfig)  => TapKey,\n  // Converts a script into a tapleaf (for script-based spending).\n  encodeScript : (script: ScriptData, version?: number) => string,\n  // Checks the validity of a given leaf target and control block.\n  checkPath    : (  \n    tapkey : Bytes, \n    target : Bytes, \n    cblock : Bytes, \n    config ?: TapConfig  \n  ) => boolean,  \n  // Gives access to the various sub-tools (described below).\n  tree  : TreeTool,\n  tweak : TweakTool,\n  util  : UtilTool\n}\n\ninterface TapConfig {\n  isPrivate ?: boolean\n  target    ?: Bytes\n  tree      ?: TapTree\n  throws    ?: boolean\n  version   ?: number\n}\n\ntype TapKey = [\n  tapkey : string,  // The tweaked public key.\n  cblock : string   // The control block needed for spending the tapleaf target.\n]\n```\n\n#### Examples\n\nExample of tapping a key with no scripts (key-spend).\n\n```ts\nconst [ tapkey ] = Tap.getPubKey(pubkey)\n```\n\nExample of tapping a key with a single script and returning a proof.\n\n```ts\n// Encode the script as bytes.\nconst bytes = Script.encode([ 'script' ])\n// Convert the bytes into a tapleaf.\nconst target = Tap.tree.getLeaf(bytes)\n// Provide the tapleaf as a target for generating the proof.\nconst [ tapkey, cblock ] = Tap.getPubKey(pubkey, { target })\n```\n\nExample of tapping a key with many scripts.\n\n```ts\nconst scripts = [\n  [ 'scripta' ],\n  [ 'scriptb' ],\n  [ 'scriptc' ]\n]\n\n// Convert the scripts into an array of tap leaves.\nconst tree = scripts\n  .map(e => Script.encode(e))\n  .map(e => Tap.tree.getLeaf(e))\n\n// Optional: You can also add data to the tree.\nconst bytes = encodeData('some data')\nconst leaf  = Tap.tree.getLeaf(bytes)\ntree.push(leaf)\n\n// Select a target leaf for generating the proof.\nconst target = tree[0]\n\n// Provide the tree and target leaf as arguments.\nconst [ tapkey, cblock ] = Tap.getPubKey(pubkey, { tree, target })\n```\n\n### Tree Tool\n\nThis tool helps with creating a tree of scripts / data, plus the proofs to validate items in the tree.\n\n```ts\nTap.tree = {\n  // Returns a 'hashtag' used for padding. Mainly for internal use.\n  getTag    : (tag : string) => Buff,\n  // Returns a 'tapleaf' used for building a tree. \n  getLeaf   : (data : Bytes, version ?: number) => string,\n  // Returns a 'branch' which combines two leaves (or branches).\n  getBranch : (leafA : string, leafB : string) => string,\n  // Returns the root hash of a tree.\n  getRoot   : (leaves : TapTree) => Buff,\n}\n\n// A tree is an array of leaves, formatted as strings.\n// These arrays can also be nested in multiple layers.\ntype TapTree = Array<string | string[]>\n```\n\n### Tweak Tool\n\nThis tool helps with tweaking public / secret (private) keys.\n\n```ts\nTap.tweak = {\n  // Return a tweaked private key using the provided raw data.\n  getSeckey   : (seckey: Bytes, data ?: Bytes | undefined) => Buff,\n  // Return a tweaked public key using the provided raw data.\n  getPubkey   : (pubkey: Bytes, data ?: Bytes | undefined) => Buff,\n  // Return a 'taptweak' which is used for key tweaking.\n  getTweak    : (key : Bytes, data ?: Bytes, isPrivate ?: boolean) => Buff,\n  // Return a tweaked secret key using the provided tweak.\n  tweakSeckey : (seckey: Bytes, tweak: Bytes) => Buff,\n  // Return a tweaked public key using the provided tweak.\n  tweakPubkey : (seckey: Bytes, tweak: Bytes) => Buff\n}\n```\n\n### Util Tool\n\nThis tool provides helper methods for reading and parsing data related to taproot.\n\n```ts\nTap.util = {\n  readCtrlBlock : (cblock : Bytes) => CtrlBlock,\n  readParityBit : (parity ?: string | number) => number\n}\n\ninterface CtrlBlock {\n  version : number\n  parity  : number\n  intkey  : Buff\n  paths   : string[]\n}\n```\n\n#### Example\n\n```ts\nconst cblock = 'c1187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27'\nconst { intkey, parity, paths, version } = Tap.util.readCtrlBlock(cblock)\n// Expected output, with key formatted as hex instead of bytes (for readability).\n{\n  intkey: '187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27',\n  parity: 3,\n  paths: [],\n  version: 192\n}\n```\n\n### Tx Tool\n\nThis tool helps with parsing / serializing transaction data.\n\n```ts\nTx = {\n  // Create a transaction object from partial JSON. \n  // Any missing fields will be repalced with default values.\n  create : (data : Partial<TxData>) => TxData,\n  // Serialize a JSON transaction into a hex-encoded string.\n  encode : (\n    txdata       : TxData,  // The transaction JSON.\n    omitWitness ?: boolean  // If you wish to omit the witness data.\n  ) => string,\n  // Parse a hex-encoded transaction into a JSON object.\n  decode : (bytes : string | Uint8Array) => TxData,\n  // Normalize transaction data to a particular format.\n  fmt : {\n    // Convert transaction data into JSON format.\n    toJson  : (txdata ?: TxData | Bytes) => TxData,\n    // Convert transaction data into a byte format.\n    toBytes : (txdata ?: TxData | Bytes) => Buff\n  },\n  util : {\n    // Get the transaction Id of a transaction.\n    getTxid : (txdata : TxData | Bytes) => Buff,\n    // Get the size data of a transaction.\n    getTxSize : (txdata : TxData | Bytes) => TxSizeData,\n    // Parse a scriptPubKey and get the type plus hash data.\n    readScriptPubKey : (script : ScriptData) => ScriptPubKeyData,\n    // Parse an array of witness data into named values.\n    readWitness : (witness : ScriptData[])  => WitnessData\n  }\n}\n\ninterface TxData {\n  version  ?: number           // The transaction verion. Defaults to version 2.\n  vin       : InputData[]      // An array of transaction inputs.\n  vout      : OutputData[]     // An array of transaction outputs.\n  locktime ?: LockData         // The locktime of the transaction. Defautls to 0.\n}\n\ninterface InputData {\n  txid : string               // The txid of the UTXO being spent.\n  vout : number               // The output index of the UTXO being spent.\n  prevout   ?: OutputData     // The output data of the UTXO being spent.\n  scriptSig ?: ScriptData     // The ScriptSig field (mostly deprecated).\n  sequence  ?: SequenceData   // The sequence field for the input.\n  witness   ?: ScriptData[]   // An array of witness data for the input.\n}\n\ninterface OutputData {\n  value : number | bigint     // The satoshi value of the output.\n  scriptPubKey : ScriptData   // The locking script data.\n}\n\nexport interface ScriptPubKeyData {\n  type : OutputType\n  data : Buff\n}\n\ninterface WitnessData {\n  annex  : Buff | null  // The annex data (if present) or null.\n  cblock : Buff | null  // The control block (if present) or null.\n  script : Buff | null  // The redeem script (if present) or null.\n  params : Bytes[]      // Any remaining witness arguments.\n}\n\ninterface TxSizeData {\n  size   : number       // Size of the transaction in bytes.\n  bsize  : number       // Base size of the tx (without witness data).\n  vsize  : number       // Size of the tx with witness discount applied.\n  weight : number       // Used to calculate the vsize of the tx.\n}\n\ntype SequenceData = string | number\ntype LockData     = number\ntype ScriptData   = Bytes  | Word[]\ntype Word         = string | number | Uint8Array\ntype Bytes        = string | Uint8Array\n```\n\n#### Transaction Object\n\nThis is an example transaction in JSON format.\n\n```ts\nconst txdata = {\n  version: 2\n  vin: [\n    {\n      txid: '1351f611fa0ae6124d0f55c625ae5c929ca09ae93f9e88656a4a82d160d99052',\n      vout: 0,\n      prevout: { \n        value: 10000,\n        scriptPubkey: '512005a18fccd1909f3317e4dd7f11257e4428884902b1c7466c34e7f490e0e627da'\n        \n      },\n      sequence: 0xfffffffd,\n      witness: []\n    }\n  ],\n  vout: [\n    { \n      value: 9000, \n      address: 'bcrt1pqksclnx3jz0nx9lym4l3zft7gs5gsjgzk8r5vmp5ul6fpc8xyldqaxu8ys'\n    }\n  ],\n  locktime: 0\n}\n```\n\n## Example Transactions\n\nHere are a few partial examples to help demonstrate using the library. Check out the [`test/example/taproot`](test/example/taproot/) directory to see a full implementation of each example.\n\nPlease feel free to contribute more!\n\n### Basic Pay-to-Pubkey Spending\n\nFull example: [keyspend.test.ts](test/example/taproot/keyspend.test.ts)\n\n```ts\n// Create a keypair to use for testing.\nconst secret = 'ccd54b99acec77d0537b01431579baef998efac6b08e9564bc3047b20ec1bb4c'\nconst seckey = new SecretKey(secret, { type: 'taproot' })\nconst pubkey = seckey.pub\n\n// For key spends, we need to get the tweaked versions\n// of the secret key and public key.\nconst [ tseckey ] = Tap.getSecKey(seckey)\nconst [ tpubkey ] = Tap.getPubKey(pubkey)\n\n// Optional: You could also derive the public key from the tweaked secret key.\nconst _tpubkey_example = new SecretKey(tseckey).pub.x.hex\n\n// A taproot address is simply the tweaked public key, encoded in bech32 format.\nconst address = Address.p2tr.fromPubKey(tpubkey, 'regtest')\n\n/* NOTE: To continue with this example, send 100_000 sats to the above address.\n  You will also need to make a note of the txid and vout of that transaction,\n  so that you can include that information below in the redeem tx.\n*/ \n\nconst txdata = Tx.create({\n  vin  : [{\n    // Use the txid of the funding transaction used to send the sats.\n    txid: '1ec5b5403bbc7f26a5d3a3ee30d69166a19fa81b49928f010af38fa96986d472',\n    // Specify the index value of the output that you are going to spend from.\n    vout: 1,\n    // Also include the value and script of that ouput.\n    prevout: {\n      // Feel free to change this if you sent a different amount.\n      value: 100_000,\n      // This is what our address looks like in script form.\n      scriptPubKey: [ 'OP_1', tpubkey ]\n    },\n  }],\n  vout : [{\n    // We are leaving behind 1000 sats as a fee to the miners.\n    value: 99_000,\n    // This is the new script that we are locking our funds to.\n    scriptPubKey: Address.toScriptPubKey('bcrt1q6zpf4gefu4ckuud3pjch563nm7x27u4ruahz3y')\n  }]\n})\n\n// For this example, we are signing for input 0 of our transaction,\n// using the tweaked secret key.\nconst sig = Signer.taproot.sign(tseckey, txdata, 0)\n\n// Let's add this signature to our witness data for input 0.\ntxdata.vin[0].witness = [ sig ]\n\n// Check if the signature and transaction are valid.\nconst isValid = await Signer.taproot.verify(txdata, 0)\n```\n### Basic Pay-to-TapScript\n\nFull example: [tapscript.test.ts](test/example/taproot/tapscript.test.ts)\n\n```ts\nconst secret = '0a7d01d1c2e1592a02ea7671bb79ecd31d8d5e660b008f4b10e67787f4f24712'\nconst seckey = new SecretKey(secret, { type: 'taproot' })\nconst pubkey = seckey.pub\n\n// Specify a basic script to use for testing.\nconst script = [ pubkey, 'OP_CHECKSIG' ]\nconst sbytes = Script.encode(script)\n\n// For tapscript spends, we need to convert this script into a 'tapleaf'.\nconst tapleaf = Tap.tree.getLeaf(sbytes)\n\n// Optional: There is a convenience method that converts scripts directly.\nconst _tapleaf = Tap.encodeScript(script)\n\n// Generate a tapkey that includes our leaf script. Also, create a merlke proof \n// (cblock) that targets our leaf and proves its inclusion in the tapkey.\nconst [ tpubkey, cblock ] = Tap.getPubKey(pubkey, { target: tapleaf })\n\n// A taproot address is simply the tweaked public key, encoded in bech32 format.\nconst address = Address.p2tr.fromPubKey(tpubkey, 'regtest')\n\n/* NOTE: To continue with this example, send 100_000 sats to the above address.\n  You will also need to make a note of the txid and vout of that transaction,\n  so that you can include that information below in the redeem tx.\n*/ \n\nconst txdata = Tx.create({\n  vin  : [{\n    // Use the txid of the funding transaction used to send the sats.\n    txid: '181508e3be1107372f1ffcbd52de87b2c3e7c8b2495f1bc25f8cf42c0ae167c2',\n    // Specify the index value of the output that you are going to spend from.\n    vout: 0,\n    // Also include the value and script of that ouput.\n    prevout: {\n      // Feel free to change this if you sent a different amount.\n      value: 100_000,\n      // This is what our address looks like in script form.\n      scriptPubKey: [ 'OP_1', tpubkey ]\n    },\n  }],\n  vout : [{\n    // We are leaving behind 1000 sats as a fee to the miners.\n    value: 99_000,\n    // This is the new script that we are locking our funds to.\n    scriptPubKey: Address.toScriptPubKey('bcrt1q6zpf4gefu4ckuud3pjch563nm7x27u4ruahz3y')\n  }]\n})\n\n// For this example, we are signing for input 0 of our transaction,\n// using the untweaked secret key. We are also extending the signature \n// to include a commitment to the tapleaf script that we wish to use.\nconst sig = Signer.taproot.sign(seckey, txdata, 0, { extension: tapleaf })\n\n// Add the signature to our witness data for input 0, along with the script\n// and merkle proof (cblock) for the script.\ntxdata.vin[0].witness = [ sig.hex, script, cblock ]\n\n// Check if the signature is valid for the provided public key, and that the\n// transaction is also valid (the merkle proof will be validated as well).\nconst isValid = await Signer.taproot.verify(txdata, 0, { pubkey })\n```\n\n### Create / Spend from a Tree of Scripts\n\nFull example: [taptree.test.ts](test/example/taproot/taptree.test.ts)\n\n```ts\n// Create a keypair to use for testing.\nconst secret = '0a7d01d1c2e1592a02ea7671bb79ecd31d8d5e660b008f4b10e67787f4f24712'\nconst seckey = new SecretKey(secret, { type: 'taproot' })\nconst pubkey = seckey.pub\n\n// Specify an array of scripts to use for testing.\nconst scripts = [\n  [ 1, 7, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],\n  [ 2, 6, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],\n  [ 3, 5, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],\n  [ 4, 4, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],\n  [ 5, 3, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],\n  [ 6, 2, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],\n  [ 7, 1, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ]\n]\n\n// Convert our array of scripts into tapleaves.\nconst tree = scripts.map(s => Tap.encodeScript(s))\n\n// Pick one of our scripts as a target for spending.\nconst index  = Math.floor(Math.random() * 10) % 7\nconst script = scripts[index]\nconst target = Tap.encodeScript(script)\n\n// Generate a tapkey that includes our tree. Also, create a merlke proof \n// (cblock) that targets our leaf and proves its inclusion in the tapkey.\nconst [ tpubkey, cblock ] = Tap.getPubKey(pubkey, { tree, target })\n\n// A taproot address is simply the tweaked public key, encoded in bech32 format.\nconst address = Address.p2tr.fromPubKey(tpubkey, 'regtest')\n\n/* NOTE: To continue with this example, send 100_000 sats to the above address.\n * You will also need to make a note of the txid and vout of that transaction,\n * so that you can include that information below in the redeem tx.\n */ \n\nconst txdata = Tx.create({\n  vin  : [{\n    // Use the txid of the funding transaction used to send the sats.\n    txid: 'e0b1b0aea95095bf7e113c37562a51cb8c3f50f5145c17952e766f7a84fcc5d7',\n    // Specify the index value of the output that you are going to spend from.\n    vout: 0,\n    // Also include the value and script of that ouput.\n    prevout: {\n      // Feel free to change this if you sent a different amount.\n      value: 100_000,\n      // This is what our address looks like in script form.\n      scriptPubKey: [ 'OP_1', tpubkey ]\n    },\n  }],\n  vout : [{\n    // We are leaving behind 1000 sats as a fee to the miners.\n    value: 99_000,\n    // This is the new script that we are locking our funds to.\n    scriptPubKey: Address.toScriptPubKey('bcrt1q6zpf4gefu4ckuud3pjch563nm7x27u4ruahz3y')\n  }]\n})\n\n// For this example, we are signing for input 0 of our transaction,\n// using the untweaked secret key. We are also extending the signature \n// to include a commitment to the tapleaf script that we wish to use.\nconst sig = Signer.taproot.sign(seckey, txdata, 0, { extension: target })\n\n// Add the signature to our witness data for input 0, along with the script\n// and merkle proof (cblock) for the script.\ntxdata.vin[0].witness = [ sig.hex, script, cblock ]\n\n// Check if the signature is valid for the provided public key, and that the\n// transaction is also valid (the merkle proof will be validated as well).\nconst isValid = await Signer.taproot.verify(txdata, 0, { pubkey })\n```\n\n### Create / Publish an Inscription\n\nCreating an inscription is a three-step process:\n 1. We create a script for publishing the inscription, and convert it into a bitcoin address.\n 2. Send funds to the bitcoin address.\n 3. Create a redeem transaction, which claims the previous funds (and publishes the data).\n\nFull example: [inscribe.test.ts](test/example/taproot/inscribe.test.ts)\n\n```ts\n// The 'marker' bytes. Part of the ordinal inscription format.\nconst marker   = Buff.encode('ord')\n/* Specify the media type of the file. Applications use this when rendering \n  * content. See: https://developer.mozilla.org/en-US/docs/Glossary/MIME_type \n  */\nconst mimetype = Buff.encode('image/png')\n// Create a keypair to use for testing.\nconst secret = '0a7d01d1c2e1592a02ea7671bb79ecd31d8d5e660b008f4b10e67787f4f24712'\nconst seckey = new SecretKey(secret, { type: 'taproot' })\nconst pubkey = seckey.pub\n// Basic format of an 'inscription' script.\nconst script  = [ pubkey, 'OP_CHECKSIG', 'OP_0', 'OP_IF', marker, '01', mimetype, 'OP_0', imgdata, 'OP_ENDIF' ]\n// For tapscript spends, we need to convert this script into a 'tapleaf'.\nconst tapleaf = Tap.encodeScript(script)\n// Generate a tapkey that includes our leaf script. Also, create a merlke proof \n// (cblock) that targets our leaf and proves its inclusion in the tapkey.\nconst [ tpubkey, cblock ] = Tap.getPubKey(pubkey, { target: tapleaf })\n// A taproot address is simply the tweaked public key, encoded in bech32 format.\nconst address = Address.p2tr.fromPubKey(tpubkey, 'regtest')\n\n/* NOTE: To continue with this example, send 100_000 sats to the above address.\n * You will also need to make a note of the txid and vout of that transaction,\n * so that you can include that information below in the redeem tx.\n */ \n\nconst txdata = Tx.create({\n  vin  : [{\n    // Use the txid of the funding transaction used to send the sats.\n    txid: 'b8ed81aca92cd85458966de90bc0ab03409a321758c09e46090988b783459a4d',\n    // Specify the index value of the output that you are going to spend from.\n    vout: 0,\n    // Also include the value and script of that ouput.\n    prevout: {\n      // Feel free to change this if you sent a different amount.\n      value: 100_000,\n      // This is what our address looks like in script form.\n      scriptPubKey: [ 'OP_1', tpubkey ]\n    },\n  }],\n  vout : [{\n    // We are leaving behind 1000 sats as a fee to the miners.\n    value: 99_000,\n    // This is the new script that we are locking our funds to.\n    scriptPubKey: Address.toScriptPubKey('bcrt1q6zpf4gefu4ckuud3pjch563nm7x27u4ruahz3y')\n  }]\n})\n\n// For this example, we are signing for input 0 of our transaction,\n// using the untweaked secret key. We are also extending the signature \n// to include a commitment to the tapleaf script that we wish to use.\nconst sig = Signer.taproot.sign(seckey, txdata, 0, { extension: tapleaf })\n\n// Add the signature to our witness data for input 0, along with the script\n// and merkle proof (cblock) for the script.\ntxdata.vin[0].witness = [ sig, script, cblock ]\n\n// Check if the signature is valid for the provided public key, and that the\n// transaction is also valid (the merkle proof will be validated as well).\nconst isValid = await Signer.taproot.verify(txdata, 0, { pubkey, throws: true })\n\n// You can publish your transaction data using 'sendrawtransaction' in Bitcoin Core, or you \n// can use an external API (such as https://mempool.space/docs/api/rest#post-transaction).\n```\n\nMore examples to come!\n\n## Development / Testing\n\nThis library uses yarn for package management, tape for writing tests, and rollup for bundling cross-platform compatible code. Here are a few scripts that are useful for development.\n\n```bash\n## Compiles types and builds release candidates in /dist folder.\nyarn build\n## Run any typescript file using real-time compilation.\nyarn start contrib/example.ts\n## Runs all tests listed in test/tape.ts \nyarn test\n## Full macro script for generating a new release candidate.\nyarn release\n```\n\n## Bugs / Issues\n\nIf you run into any bugs or have any questions, please submit an issue ticket.\n\n## Contribution\n\nFeel free to fork and make contributions. Suggestions are welcome!\n\n## Future Roadmap\n\n - Add signature and validation for ecdsa (segwit and earlier).\n - Refactor and stress-test tree compilation with many (many) leaves.\n - Allow arbitrary ordering of tree elements.\n - Write more unit and vector tests (cover all the things).\n\n## Dependencies\n\nThis library contains minimal dependencies.  \n\n**Buff-Utils**  \nThe swiss-army-knife of byte manipulation.  \nhttps://github.com/cmdruid/buff-utils\n\n**Crypto-Utils**  \nUser-friendly cryptography tools.  \nhttps://github.com/cmdruid/crypto-utils\n\n## Resources  \n\n**BIP340 Wiki Page**  \nThis BIP covers schnorr signatures and verification.  \nhttps://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki\n\n**BIP341 Wiki Page**  \nThis BIP covers the construction of trees, signature hashes, and proofs.  \nhttps://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki\n\n**BIP342 Wiki Page**  \nThis BIP covers changes to opcodes and signature verification.  \nhttps://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki\n\n**Tapscript example using Tap**  \nThis is a guide on how to use a command-line tool called btcdeb and Tap.  \nThis tool will help you create a taproot transaction from scratch, which  \nis great for learning (and to debug any issues with this library :-)).  \nhttps://github.com/bitcoin-core/btcdeb/blob/master/doc/tapscript-example-with-tap.md\n\n## License\n\nUse this library however you want!\n\n## Contact\n\nYou can find me on twitter at `@btctechsupport` or on nostr at `npub1gg5uy8cpqx4u8wj9yvlpwm5ht757vudmrzn8y27lwunt5f2ytlusklulq3`","readmeFilename":"README.md"}