{"_id":"@cardano-slips/verifier","_rev":"7-7a99f22f879a21efa1abb640406c1b5e","name":"@cardano-slips/verifier","dist-tags":{"latest":"0.4.0"},"versions":{"0.0.0":{"name":"@cardano-slips/verifier","version":"0.0.0","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"license":"MIT","_id":"@cardano-slips/verifier@0.0.0","maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","dist":{"shasum":"7430669b45c60c86f457590b6133b97f9c89f345","tarball":"https://registry.npmjs.org/@cardano-slips/verifier/-/verifier-0.0.0.tgz","fileCount":8,"integrity":"sha512-r7QmsaJqbNAKp/93OIVIKsVYs1knaVAAq6DZIcZULcGq/jC9IqbGqZaxgPI2FCJPjX3wWubHyN3RbFPO/IdMAQ==","signatures":[{"sig":"MEYCIQDSqRJikvyoMc/INtqIL9+pSMY2y7MB6g5PIsgyL0yysgIhAKk2EDz1Z5pKhQUEKL4Dx54bde/lW/Brbu5LTJnW6nMY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":6957},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsc -b tsconfig.build.json","clean":"rm -rf dist build coverage .tsbuildinfo .turbo","typecheck":"tsc -b tsconfig.src.json && tsc -p tsconfig.test.json"},"_npmUser":{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"},"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","dependencies":{"@cardano-slips/core":"^0.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/verifier_0.0.0_1787519316667_0.6235702453203218","host":"s3://npm-registry-packages-npm-production"}},"0.0.1":{"name":"@cardano-slips/verifier","version":"0.0.1","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"license":"MIT","_id":"@cardano-slips/verifier@0.0.1","maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","dist":{"shasum":"4a03829538c6b4709baba62418db5773faae3b9d","tarball":"https://registry.npmjs.org/@cardano-slips/verifier/-/verifier-0.0.1.tgz","fileCount":8,"integrity":"sha512-VdkkImQ2Fgzxml7N/JtqdpxNIr7Yv3HupYtD344CoBpWDijAMkL2kxVWifdstOYUQSqqmnC1c73jIY1YBo0R/Q==","signatures":[{"sig":"MEUCIAkD8nfP13Z8IuXWHn6TxQncqpSu2Yg5VdIb8pWafEUFAiEA8JkitCxuRaj8cnremOS7Rq4hs94/ygQXW7MluOL/Ppw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-slips%2fverifier@0.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":6957},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsc -b tsconfig.build.json","clean":"rm -rf dist build coverage .tsbuildinfo .turbo","typecheck":"tsc -b tsconfig.src.json && tsc -p tsconfig.test.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:812447e4-3bfa-4cd7-a028-3b32e582aec1"}},"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","directories":{},"sideEffects":false,"_nodeVersion":"26.0.0","dependencies":{"@cardano-slips/core":"^0.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/verifier_0.0.1_1787519819886_0.09497353934970376","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@cardano-slips/verifier","version":"0.0.2","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"license":"MIT","_id":"@cardano-slips/verifier@0.0.2","maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","dist":{"shasum":"3fa561e39c08a905a5add25b2faa136a931d339b","tarball":"https://registry.npmjs.org/@cardano-slips/verifier/-/verifier-0.0.2.tgz","fileCount":8,"integrity":"sha512-N/0RrsssMdTOEr9Ug4OxeRSUYrWct/AuvoIFhvHZBpql3ZgR15DhLO8ZfTplTLwPx7kVJNnXSmSEtubhNRvfdA==","signatures":[{"sig":"MEQCIFjfZvG6eS0Q7hTCtkAGGbZDadP+s79Ohgv1ChIcht6tAiBoOxlA1d90jdlYIgrXOsSgUwun4x+GIp0lrpGFJECgbw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-slips%2fverifier@0.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":6062},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsc -b tsconfig.build.json","clean":"rm -rf dist build coverage .tsbuildinfo .turbo","typecheck":"tsc -b tsconfig.src.json && tsc -p tsconfig.test.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:812447e4-3bfa-4cd7-a028-3b32e582aec1"}},"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","directories":{},"sideEffects":false,"_nodeVersion":"26.0.0","dependencies":{"@cardano-slips/core":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/verifier_0.0.2_1787700597174_0.05472159469260163","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@cardano-slips/verifier","version":"0.1.0","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"license":"MIT","_id":"@cardano-slips/verifier@0.1.0","maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","dist":{"shasum":"5187b4e10e81df6f70b50e7eb34aeb7d44708d94","tarball":"https://registry.npmjs.org/@cardano-slips/verifier/-/verifier-0.1.0.tgz","fileCount":23,"integrity":"sha512-J+jRbdz8K8rZtVE/OUzzbcYauW15k45EmI8bvulnWnAFv/UOceFzFpvJJQMyZK7m8JjSRiIKlL6b46q2cf62VA==","signatures":[{"sig":"MEYCIQDf8UzQcKaQVI7NIGtgjuLpds8I2UWXrlaOjL+5R15v8QIhAJkOniZwmky0KSK2CNnld0ULZ/ucmFdbg6hjMhX0MnM1","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-slips%2fverifier@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":151815},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsc -b tsconfig.build.json","clean":"rm -rf dist build coverage .tsbuildinfo .turbo","typecheck":"tsc -b tsconfig.src.json && tsc -p tsconfig.test.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:812447e4-3bfa-4cd7-a028-3b32e582aec1"}},"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","directories":{},"sideEffects":false,"_nodeVersion":"26.0.0","dependencies":{"effect":"^3.22.1","@cardano-slips/core":"^0.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@noble/hashes":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/verifier_0.1.0_1787903845123_0.04932245085854747","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cardano-slips/verifier","version":"0.2.0","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"license":"MIT","_id":"@cardano-slips/verifier@0.2.0","maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","dist":{"shasum":"92f03e399d9922c1e886056b7b5d98451121f891","tarball":"https://registry.npmjs.org/@cardano-slips/verifier/-/verifier-0.2.0.tgz","fileCount":73,"integrity":"sha512-pRZZ7il06FYJp8smEcK5Z8bk/Nz9qOaksDqNEMGVetFFkDcU1Odsxsk17yp8zmyL+ZavL+j3/EiScNMRDmwiiA==","signatures":[{"sig":"MEUCIQCA7oW5UyY1FHPthW5UpLCPcz1z48IdrTx9D70LOEfMjQIgRfcOKS8vAKZrgloX2sFBO7ocUHBB2ZaSrGc+RkjlXtM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDq0re824e/PF8+5mr8Nu86RjIOLnMYNM+ufq0+iTiFxgIgVS++1qghfptGj8AX8e2UG0ODzUl7WmIBVpxyn/75pbs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-slips%2fverifier@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":346802},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsc -b tsconfig.build.json","clean":"rm -rf dist build coverage .tsbuildinfo .turbo","typecheck":"tsc -b tsconfig.src.json && tsc -p tsconfig.test.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:812447e4-3bfa-4cd7-a028-3b32e582aec1"}},"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","directories":{},"sideEffects":false,"_nodeVersion":"26.0.0","dependencies":{"effect":"^3.22.1","@cardano-slips/core":"^0.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@noble/hashes":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/verifier_0.2.0_1789069856239_0.7879654001465","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@cardano-slips/verifier","version":"0.3.0","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"license":"MIT","_id":"@cardano-slips/verifier@0.3.0","maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","dist":{"shasum":"be4e5c40790f7120d3c7b922397a8616e6b8bb55","tarball":"https://registry.npmjs.org/@cardano-slips/verifier/-/verifier-0.3.0.tgz","fileCount":73,"integrity":"sha512-rNa6Elx1rNfEvc4l3Qbh92x44J2bXpWNSIK14S73spLVxGz38gbtfXS/1hij+5ftkADcBRaFBWSbZ32RS/7hjA==","signatures":[{"sig":"MEUCIQDuvv1S8Dksf3EdAEaOQQ9f/WuDv/dgywv5v0xXzQQOrAIgBAUloFGPRHOykKsK0KYzIBvMS9mv3LVh4HX/dI70TPo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHsJGurfXgbcCKuN8/RKbFZ0RrgkeZK+TNHz0ikezOc5AiEArWPFVyxiGlOs7xYHhVKvUDRaAyajTJJ/NsQUbY3g8s0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-slips%2fverifier@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":355421},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"lint":"eslint .","test":"vitest run","build":"tsc -b tsconfig.build.json","clean":"rm -rf dist build coverage .tsbuildinfo .turbo","typecheck":"tsc -b tsconfig.src.json && tsc -p tsconfig.test.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:812447e4-3bfa-4cd7-a028-3b32e582aec1"}},"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","directories":{},"sideEffects":false,"_nodeVersion":"26.0.0","dependencies":{"effect":"^3.22.1","@cardano-slips/core":"^0.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@noble/hashes":"^2.0.1"},"_npmOperationalInternal":{"tmp":"tmp/verifier_0.3.0_1789588001582_0.48473949716363784","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"_id":"@cardano-slips/verifier@0.4.0","bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","dist":{"shasum":"bd7cb28e05ad7db562840d95c1a1924abef38564","tarball":"https://registry.npmjs.org/@cardano-slips/verifier/-/verifier-0.4.0.tgz","fileCount":73,"integrity":"sha512-qwxTySJkFu4bl1ogzrfjvxEVbs40pbMkvD4Rkme0lGicqzYYn149kbzMDcNCtohMNpBJqS4sU2PSR0TgXK/G1A==","signatures":[{"sig":"MEYCIQDgDkTOGQ4qqKcOXMRrc7Jat5JTbTFgQgPKs+FxIkNtQwIhAL/8+hZGjsFsEKN5GFx30WAxbQz9FNpjmBhVrXr0b2G+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCNqqwXKaNTGdykjotQoJZo4iFTvJzQ1y9L9PacQt1VagIhAIea0Kw6qv1lSrAkSG7bQy2D7kpUEDyGpYV1CdyBrQP1"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-slips%2fverifier@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":356180},"name":"@cardano-slips/verifier","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"license":"MIT","scripts":{"lint":"eslint .","test":"vitest run","build":"tsc -b tsconfig.build.json","clean":"rm -rf dist build coverage .tsbuildinfo .turbo","typecheck":"tsc -b tsconfig.src.json && tsc -p tsconfig.test.json"},"version":"0.4.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"812447e4-3bfa-4cd7-a028-3b32e582aec1"}},"homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","directories":{},"maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"sideEffects":false,"_nodeVersion":"26.0.0","dependencies":{"effect":"^3.22.1","@cardano-slips/core":"^0.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@noble/hashes":"^2.0.1"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/verifier_0.4.0_1790762260286_0.08130623440275464"}}},"time":{"created":"2026-08-23T21:08:36.548Z","modified":"2026-09-30T09:57:40.769Z","0.0.0":"2026-08-23T21:08:36.809Z","0.0.1":"2026-08-23T21:17:00.026Z","0.0.2":"2026-08-25T23:29:57.319Z","0.1.0":"2026-08-28T07:57:25.278Z","0.2.0":"2026-09-10T19:50:56.341Z","0.3.0":"2026-09-16T19:46:41.800Z","0.4.0":"2026-09-30T09:57:40.368Z"},"bugs":"https://github.com/emmanuel-musau/cardano-slips/issues","license":"MIT","homepage":"https://github.com/emmanuel-musau/cardano-slips/tree/main/packages/verifier#readme","keywords":["cardano","cardano-slips","cbor","transaction","verification"],"repository":{"url":"git+https://github.com/emmanuel-musau/cardano-slips.git","type":"git","directory":"packages/verifier"},"description":"The security engine for Cardano Slips: decodes transaction CBOR, derives what it actually does, and compares that against what the endpoint declared","maintainers":[{"name":"emmanuel-musau","email":"emmanuelmutisya254@gmail.com"}],"readme":"# @cardano-slips/verifier\n\nThe security engine. It decodes a balanced transaction's CBOR, works out what the transaction actually does, and compares that against what the endpoint said it does. When the two disagree, signing is blocked — there is no override.\n\n```\npnpm add @cardano-slips/verifier\n```\n\n## The signature\n\n```\nverify(tx CBOR, declared metadata, user addresses, resolved inputs, protocol parameters)\n  → match | mismatch(reasons[])\n```\n\nFive arguments, and no sixth. Nothing is fetched: a transaction body carries only references to the inputs it spends, so their values are handed in; a fee ceiling, an output raised to the ledger minimum, a deposit told apart from a spend, and an expiry shown as a time all need protocol parameters, so those are handed in too. Anything the engine went and got for itself would put a network call between a person and a signature — one that can be slow, absent, or answered by whoever benefits from the answer.\n\nThat purity is what makes the attack examples worth anything. They run the same code that runs before a real signature, so \"every lying transaction was blocked\" is a property of a function rather than a claim about a system. `test/no-io.test.ts` is what keeps it true.\n\n## What it derives\n\n| Derived | Rendered as |\n| --- | --- |\n| net ADA delta for the user's addresses, exact fee, deposits | \"You pay 0.17 ADA (fee)\", \"Deposit 2.00 ADA (refundable)\" |\n| net asset deltas per policy and asset | \"You receive 25 USDM\" |\n| certificates | \"Delegate → pool1xyz\" |\n| withdrawals | \"Withdraws N ADA rewards\" |\n| mint and burn | assets created or destroyed |\n| validity interval | \"Expires in 4m 12s\" |\n\nUndeclared effects — an extra output, an unexpected certificate — are a mismatch, not an omission. The rules and the reason vocabulary are normative: see [The comparison](../../spec/CIP-XXXX/README.md#the-comparison).\n\n## Reading the transaction\n\nThe first step is `decodeTransaction`, which takes the bytes and gives back a\nConway transaction body plus the byte range the body occupied:\n\n```ts\nimport { decodeTransaction } from \"@cardano-slips/verifier\"\nimport { Either } from \"effect\"\n\nconst read = decodeTransaction(bytes)\nif (Either.isLeft(read)) {\n  read.left.refusal // \"UnknownCertificateType\"\n  read.left.at // the byte it happened at\n} else {\n  read.right.body.fee\n  read.right.bodyBytes // hash these for the transaction id\n}\n```\n\nTwo things about it are deliberate.\n\n**It fails closed.** A body key we do not model, a certificate type from an era\nthat shipped after us, an output that is neither of the two known shapes: each\none refuses, by name, at a byte offset. A decoder that tolerated them would\nderive effects from a transaction it only partly read, and the effect it missed\nis the one nothing downstream can flag.\n\n**It hands back the body's bytes, not a re-encode.** The transaction id is\nBLAKE2b-256 over the body exactly as it arrived. Hashing our own re-encoding of\nit would give a different id for any transaction whose body was not written the\nway we would write it. `extractTransactionBody` does that half alone, for a\ncaller that needs the commit and not the contents.\n\nThe reasoning is in [ADR-0010](../../docs/DECISIONS/0010-cbor-decode-approach.md);\n[ADR-0012](../../docs/DECISIONS/0012-decode-test-oracle.md) covers how it is tested.\n\n## Working out the lovelace\n\n`deriveLovelace` is the arithmetic: what the transaction does to a person's ADA,\nthe fee it states, and the deposits it locks up or hands back.\n\n```ts\nimport { decodeTransaction, deriveLovelace } from \"@cardano-slips/verifier\"\nimport { Either } from \"effect\"\n\nconst derived = deriveLovelace({\n  transaction, // from decodeTransaction\n  userAddresses, // every address the wallet reports, its reward account included\n  resolvedInputs, // the output each input points at, with its value\n  protocolParameters\n})\n\nif (Either.isRight(derived)) {\n  derived.right.user.ada // spent less received: positive is lovelace leaving\n  derived.right.fee // exactly what the body states\n  derived.right.deposits // \"Deposit 2.00 ADA (refundable)\"\n  derived.right.unaccounted // 0n for a transaction the engine reads completely\n}\n```\n\n**A deposit is not a cost.** It comes back, so it is listed apart from what is\nspent rather than folded into `user.ada`, and each entry says where its number\ncame from: `stated` off the certificate, `parameter` from the protocol\nparameters, or `assumed` where the body cannot settle whether the parameter\napplies — a pool already registered pays nothing to re-register, and a\ncredential registered before the parameter last changed is refunded what it\npaid rather than what the parameter says now. Each entry also carries `source`\nand `index`, which say where in the body it came from: proposal deposits and\ncertificate deposits share one array and can share a position.\n\n**Collateral is not in these figures.** It is consumed only when a script\nfails, which is the is-valid-false case the derivation refuses, so it takes no\npart in the arithmetic — but a transaction can still put collateral at risk\nwithout that showing up anywhere here. Showing that risk is not modelled yet.\n\n**`unaccounted` is the engine checking itself.** What the ledger consumes less\nwhat it produces, under this reading: inputs and withdrawals and refunds against\noutputs, fee, deposits and any treasury donation. It is `0n` for a transaction\nthe engine understands completely, and anything else is the engine saying the\narithmetic a person would be shown does not add up.\n\n## The assets\n\n`deriveAssets` is the same arithmetic per policy and asset name, and takes the\nsame four arguments.\n\n```ts\nimport { deriveAssets } from \"@cardano-slips/verifier\"\n\nconst derived = deriveAssets({ transaction, userAddresses, resolvedInputs, protocolParameters })\n\nif (Either.isRight(derived)) {\n  derived.right.user // [{ policyId, name, spent, received, delta }]\n  derived.right.unaccounted // [] for a transaction the engine reads completely\n}\n```\n\n`delta` runs the same way as `user.ada`: positive is the asset leaving,\nnegative is the asset arriving, so the person paying and the person being paid\nread the same transaction with opposite signs.\n\n**Every quantity is the raw on-chain count.** A token's decimals are a display\nconcern; ten USDM is `10000000n` here and nowhere is it `10`.\n\n**An asset that comes in and goes straight back out is not an effect.** A\nwallet holding fourteen tokens and moving one has one delta, not fourteen —\n`test/fixtures/usdm-payment.json` is exactly that transaction. `unaccounted`\nhere is what the inputs hold plus what the body mints, less what the outputs\nhold; the mint is read for that sum alone, and rendering what a transaction\ncreates or destroys belongs elsewhere.\n\n## What it does besides move value\n\nFour more, taking the same argument and refusing on the same terms.\n\n```ts\nimport { deriveCertificates, deriveMint, deriveValidity, deriveWithdrawals } from \"@cardano-slips/verifier\"\n\nderiveCertificates(derivation) // [{ kind, credential, role, ours, pool, drep, deposit, refund, index }]\nderiveWithdrawals(derivation) // [{ rewardAccount, amount, ours }]\nderiveMint(derivation) // [{ policyId, name, quantity }] — a burn is negative\nderiveValidity(derivation) // { validFrom, validUntil }, each a slot and the instant it begins\n```\n\n**A certificate carries what a person needs to read it**: what it is, the\ncredential it acts on, the pool or DRep it names, and the deposit or refund the\nledger applies to it, already joined from `deposits.ts`.\n\n**Read `role` before rendering `credential`.** Three different namespaces arrive\nin that one field — a stake credential, a DRep's own, and a committee cold key —\nand a DRep or committee key shown as a `stake1…` address is an address the\nperson does not hold. `ours` is true where the wallet reported that credential,\nin a reward account or in the stake half of one of its addresses; a credential\nit did not report is someone else's, the same rule the addresses follow.\n\n**A withdrawal is summed per reward account, and a mint per asset.** The ledger\nwrites one entry each, but both are CBOR maps nothing forces to have distinct\nkeys: two withdrawal entries rendered separately would show one account's\nrewards twice, and a policy written twice in a mint would show as a mint and a\nburn of an asset the transaction creates none of.\n\n**`validUntil` is when the transaction expires**, not the last moment it is\ngood for: the body's `invalid_hereafter` is the first slot it is no longer\nvalid. Both ends convert through the slot mapping in the protocol parameters,\nanchored at the first slot of the era in force — mainnet's Shelley era begins at\nslot 4492800, and using slot zero would put every conversion two hours out.\n\n## What every derivation holds to\n\n**An address the wallet did not report is someone else's.** That overstates what\nleaves and understates what returns, which is the safe direction: the other one\nwould hide a payment to a stranger by calling it change. An address sharing a\npayment credential but not a stake part is a different address, and is treated\nas one.\n\n**They refuse rather than guess.** An input with no supplied value would\notherwise count as zero, which is how a spend gets hidden; two readings of one\ninput disagree about what to show; and a transaction whose is-valid flag is\nfalse spends collateral instead of its inputs, which is different arithmetic.\nEvery derivation resolves the body's inputs through one shared step, so none of\nthem can grow its own idea of when to stop.\n\n## Standalone by design\n\nA wallet or an explorer can take this package on its own, without the rest of the protocol. It depends on `core` for types and on no other workspace package — never on `flow`, `server`, or any network layer.\n\n## Entry point\n\nOne export, the package root. Deep imports into `dist/` are not a supported surface, so moving a file is never a breaking change:\n\n```ts\nimport { ... } from \"@cardano-slips/verifier\"\n```\n\nMIT licensed. Issues and contribution guide: [cardano-slips](https://github.com/emmanuel-musau/cardano-slips).\n","readmeFilename":""}