{"_id":"@emberai/onchain-actions-contracts","_rev":"4-268e4a4e8f66f6dc558edd62c663bed1","name":"@emberai/onchain-actions-contracts","dist-tags":{"latest":"1.1.0"},"versions":{"0.0.0":{"name":"@emberai/onchain-actions-contracts","version":"0.0.0","license":"MIT","_id":"@emberai/onchain-actions-contracts@0.0.0","maintainers":[{"name":"tomdaniel","email":"admin@emberai.xyz"}],"homepage":"https://github.com/EmberAGI/arbitrum-vibekit#readme","bugs":{"url":"https://github.com/EmberAGI/arbitrum-vibekit/issues"},"dist":{"shasum":"804af92d791abe40679da92bea8a516f93c21da7","tarball":"https://registry.npmjs.org/@emberai/onchain-actions-contracts/-/onchain-actions-contracts-0.0.0.tgz","fileCount":2,"integrity":"sha512-6FG8Pr73ctym/V4atvjMidyvjQgj4ACVuCHLDsUAtbwJokcoPkM/jDHmkM+IKu563T7Q0uheA8JVCCROG0evUw==","signatures":[{"sig":"MEUCIQCHcJUrRH3rx8Rm+31CsIhpZWBXEicSM+rPutrGUfUrkQIgIh7+akViz+6O9eNaNSD7zU3+m262UM/ASDBBh3EaQLs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":559},"_npmUser":{"name":"tomdaniel","email":"admin@emberai.xyz"},"deprecated":"Name reservation placeholder - real package ships from EmberAGI/arbitrum-vibekit (EMB-1145) via trusted publishing","repository":{"url":"git+https://github.com/EmberAGI/arbitrum-vibekit.git","type":"git"},"_npmVersion":"11.12.1","description":"Name reservation for the neutral onchain-action contracts package (EmberAGI/arbitrum-vibekit, EMB-1145). Real releases will supersede this placeholder.","directories":{},"_nodeVersion":"24.15.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/onchain-actions-contracts_0.0.0_1784749623818_0.3180512243490652","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@emberai/onchain-actions-contracts","version":"1.0.0","license":"MIT","_id":"@emberai/onchain-actions-contracts@1.0.0","maintainers":[{"name":"tomdaniel","email":"admin@emberai.xyz"}],"homepage":"https://github.com/EmberAGI/arbitrum-vibekit#readme","bugs":{"url":"https://github.com/EmberAGI/arbitrum-vibekit/issues"},"dist":{"shasum":"4a924f8e88290c111d444a47c6b9896d8fa2af6d","tarball":"https://registry.npmjs.org/@emberai/onchain-actions-contracts/-/onchain-actions-contracts-1.0.0.tgz","fileCount":44,"integrity":"sha512-UdsyUBX3YTKapxnd6TTuBViyXCxbUy4OSK0KPKWDCnp8PfnjaYMo88ymO6wJRQ5TUo0uhTxeD2KIC86VTEcVPQ==","signatures":[{"sig":"MEUCIBFtDHUojLdDP/zQvbpV/Z6YVB9gZqhw7kRVhZ/72iA1AiEAiWSX2jm/bvr/WggpP7B6efHLRVxv1zRPQM35LCWDs94=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@emberai%2fonchain-actions-contracts@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2094685},"type":"module","exports":{"./core":{"import":{"types":"./dist/core/index.d.mts","default":"./dist/core/index.mjs"},"require":{"types":"./dist/core/index.d.cts","default":"./dist/core/index.cjs"}},"./plugins":{"import":{"types":"./dist/plugins/index.d.mts","default":"./dist/plugins/index.mjs"},"require":{"types":"./dist/plugins/index.d.cts","default":"./dist/plugins/index.cjs"}},"./endpoints":{"import":{"types":"./dist/endpoints/index.d.mts","default":"./dist/endpoints/index.mjs"},"require":{"types":"./dist/endpoints/index.d.cts","default":"./dist/endpoints/index.cjs"}},"./external-data":{"import":{"types":"./dist/external-data/index.d.mts","default":"./dist/external-data/index.mjs"},"require":{"types":"./dist/external-data/index.d.cts","default":"./dist/external-data/index.cjs"}}},"gitHead":"a0a24a0d1b9c7d9825bdb19bc4289083bc786851","scripts":{"lint":"NODE_OPTIONS=--max-old-space-size=4096 eslint src","build":"tsdown","format":"prettier --write \"src/**/*.ts\"","test:ci":"tsdown && vitest run --config vitest.config.ts","lint:fix":"NODE_OPTIONS=--max-old-space-size=4096 eslint src --fix"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:7368bfc2-2aa5-44c2-8446-4cccca55229b"}},"repository":{"url":"git+https://github.com/EmberAGI/arbitrum-vibekit.git","type":"git","directory":"typescript/onchain-actions-plugins/contracts"},"_npmVersion":"12.0.2","description":"Runtime-validatable neutral contracts for Ember onchain actions.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{},"publishConfig":{"tag":"next","access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^3.25.76","tsdown":"^0.16.1"},"peerDependencies":{"zod":"^3.25.76"},"_npmOperationalInternal":{"tmp":"tmp/onchain-actions-contracts_1.0.0_1785532954884_0.15279312228214192","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@emberai/onchain-actions-contracts","version":"1.1.0","description":"Runtime-validatable neutral contracts for Ember onchain actions.","type":"module","exports":{"./core":{"import":{"types":"./dist/core/index.d.mts","default":"./dist/core/index.mjs"},"require":{"types":"./dist/core/index.d.cts","default":"./dist/core/index.cjs"}},"./plugins":{"import":{"types":"./dist/plugins/index.d.mts","default":"./dist/plugins/index.mjs"},"require":{"types":"./dist/plugins/index.d.cts","default":"./dist/plugins/index.cjs"}},"./endpoints":{"import":{"types":"./dist/endpoints/index.d.mts","default":"./dist/endpoints/index.mjs"},"require":{"types":"./dist/endpoints/index.d.cts","default":"./dist/endpoints/index.cjs"}},"./external-data":{"import":{"types":"./dist/external-data/index.d.mts","default":"./dist/external-data/index.mjs"},"require":{"types":"./dist/external-data/index.d.cts","default":"./dist/external-data/index.cjs"}}},"sideEffects":false,"scripts":{"build":"tsdown","lint":"NODE_OPTIONS=--max-old-space-size=4096 eslint src","lint:fix":"NODE_OPTIONS=--max-old-space-size=4096 eslint src --fix","format":"prettier --write \"src/**/*.ts\"","test:ci":"tsdown && vitest run --config vitest.config.ts"},"devDependencies":{"tsdown":"^0.16.1","viem":"^2.26.3","zod":"^3.25.76"},"license":"MIT","publishConfig":{"access":"public","tag":"next"},"repository":{"type":"git","url":"git+https://github.com/EmberAGI/arbitrum-vibekit.git","directory":"typescript/onchain-actions-plugins/contracts"},"peerDependencies":{"zod":"^3.25.76"},"dependencies":{},"gitHead":"a34f7c30bdf24771976d7c9dcc06073f8da53cf0","_id":"@emberai/onchain-actions-contracts@1.1.0","bugs":{"url":"https://github.com/EmberAGI/arbitrum-vibekit/issues"},"homepage":"https://github.com/EmberAGI/arbitrum-vibekit#readme","_nodeVersion":"24.18.0","_npmVersion":"12.0.2","dist":{"integrity":"sha512-oXlwbCgwoSmCodyS2l9/bODgbNZNBXNkwyiSMrhksRbtr34UIkTHf3NtdDH8QtzeJ1dvEsjUdL7ImE2UlEj2+Q==","shasum":"20fc0daa03a568ed58f2cc24c0c334f8ac06e1eb","tarball":"https://registry.npmjs.org/@emberai/onchain-actions-contracts/-/onchain-actions-contracts-1.1.0.tgz","fileCount":45,"unpackedSize":2359382,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@emberai%2fonchain-actions-contracts@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEpvPUdfl+4jfbG7/+Jah8omztipbM66znt7PiEzVxW4AiApF4274SuGN/5JSZWNMz5LsWXd/cCVYyGyk6bUulmnYw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:7368bfc2-2aa5-44c2-8446-4cccca55229b"}},"directories":{},"maintainers":[{"name":"tomdaniel","email":"admin@emberai.xyz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/onchain-actions-contracts_1.1.0_1785889576528_0.9342056557493801"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-22T19:47:03.617Z","modified":"2026-08-05T00:26:17.069Z","0.0.0":"2026-07-22T19:47:03.952Z","1.0.0":"2026-07-31T21:22:35.035Z","1.1.0":"2026-08-05T00:26:16.663Z"},"bugs":{"url":"https://github.com/EmberAGI/arbitrum-vibekit/issues"},"license":"MIT","homepage":"https://github.com/EmberAGI/arbitrum-vibekit#readme","repository":{"type":"git","url":"git+https://github.com/EmberAGI/arbitrum-vibekit.git","directory":"typescript/onchain-actions-plugins/contracts"},"description":"Runtime-validatable neutral contracts for Ember onchain actions.","maintainers":[{"name":"tomdaniel","email":"admin@emberai.xyz"}],"readme":"# @emberai/onchain-actions-contracts\n\nNeutral, runtime-validatable contracts shared by Ember onchain-action\nproviders, plugins, endpoints, and registry consumers.\n\n## Install\n\n```bash\npnpm add @emberai/onchain-actions-contracts zod@^3.25.76\n```\n\nZod is a peer dependency. V1 requires Zod 3 so producers and consumers share\none runtime schema instance.\n\nThe package exposes four stable public subpaths:\n\n- `@emberai/onchain-actions-contracts/core`\n- `@emberai/onchain-actions-contracts/plugins`\n- `@emberai/onchain-actions-contracts/endpoints`\n- `@emberai/onchain-actions-contracts/external-data`\n\nThese subpaths are the supported import surface. The package is dependency-light\nand has no registry, provider, network, or protocol runtime.\n\n## Canonical token identity\n\n`@emberai/onchain-actions-contracts/core` exports `CanonicalTokenIdentifierV1Schema`\nand a pure chain-aware identity Interface that is the sole authority for token\nidentity comparison across the package:\n\n```ts\nimport {\n  canonicalTokenIdentityKey,\n  classifyTokenChainFamily,\n  normalizeCanonicalTokenIdentifier,\n  tokenIdentitiesAreEquivalent,\n} from '@emberai/onchain-actions-contracts/core';\n```\n\n| `chainId` | Family | Identity rule |\n| --- | --- | --- |\n| Legacy decimal Ember chain id (e.g. `42161`) | `evm` | Case-insensitive; canonicalizes to the deterministic EIP-55 checksum form. |\n| Legacy `solana` literal | `solana` | Case-sensitive; distinct casings are distinct addresses. |\n| CAIP-2 `eip155:*` | `evm` | Same as above, derived from the namespace. |\n| CAIP-2 `solana:*` | `solana` | Same as above, derived from the namespace. |\n| Any other chain id | `opaque` | Case-sensitive; never silently lowercased. |\n\nRequest uniqueness, result-order validation, and the `TokenPriceReader` host\ncapability all delegate to this Interface. Callers must not reimplement\naddress-case policy locally. `TokenPriceReader.readTokenPrices` takes\n`CanonicalTokenIdentifierV1` values directly, not raw `TokenIdentifier` input.\n`CanonicalTokenIdentifierV1` is a branded (nominal) type, not merely a\nstructural `{ chainId, address }` shape: a raw object literal does not\nsatisfy it, however well-formed its fields are. The only way to produce one\nis to parse it through `CanonicalTokenIdentifierV1Schema` — directly or via\n`normalizeCanonicalTokenIdentifier` — which is what makes this seam\nunforgeable rather than a documentation-only convention.\n\n### EIP-55 is the sole canonical evm representation\n\nEIP-55 — not lowercase — is the one canonical evm domain representation.\n`CanonicalTokenIdentifierV1Schema` requires a full `0x`-prefixed 20-byte\nhexadecimal address, accepts either legacy all-lowercase input or an\nalready-checksummed EIP-55 address, rejects an invalid mixed-case checksum\noutright, and always emits the deterministic EIP-55 checksum form. Every\nidentity operation in this Interface — normalization, canonical keying,\nequality, and token-market request/envelope validation — consumes or derives\nthat same EIP-55 representation; there is no second, lowercase-keyed\nconvention anywhere behind it.\n\n```ts\nnormalizeCanonicalTokenIdentifier({ chainId: '42161', address: '0xabc...' });\n// => { chainId: '42161', address: '0xAbC...' } -- the EIP-55 checksum form\n\nnormalizeCanonicalTokenIdentifier({ chainId: '42161', address: '0xAbC...bad-checksum' });\n// throws -- an invalid mixed-case checksum is rejected, never silently corrected\n```\n\nBecause a lowercase and an EIP-55-checksummed spelling of the same address\ncanonicalize to the same key, submitting both in one token-market request is\na true duplicate and is rejected by `TokenMarketSnapshotRequestV1Schema`,\nexactly like submitting the same address twice.\n\nLowercase is valid only as ingress a caller may submit; it is never canonical\noutput. A provider whose own wire Interface requires lowercase keeps that\nprojection inside its Adapter and normalizes back to the canonical EIP-55\nform before crossing this package's public Interface — contracts, caches,\npersistence, evidence, and public responses only ever carry EIP-55.\n\nCAIP-2 matching follows the full CAIP-2 grammar, not just the namespace: a\nnamespace is syntactically lowercase-only (`EIP155:*`/`SOLANA:*` are invalid\nCAIP-2 ids and stay `opaque`, not case-folded into `evm`/`solana`), and a\nreference containing a colon, whitespace, or more than 32 characters is\nlikewise not valid CAIP-2 syntax and stays `opaque` rather than deriving\n`evm`/`solana` semantics.\n\nEvery function in this Interface — `classifyTokenChainFamily`,\n`normalizeCanonicalTokenIdentifier`, `canonicalTokenIdentityKey`, and\n`tokenIdentitiesAreEquivalent` — validates its `chainId`/`address` input\nthrough the same non-empty/trimmed invariant before dispatching on it, so\ncalling any of them directly with an empty, all-whitespace, or\nleading/trailing-whitespace value throws instead of silently trimming or\notherwise producing a result.\n\n`canonicalTokenIdentityKey` encodes the `(chainId, address)` pair as a\n`JSON.stringify`-escaped tuple rather than delimiter concatenation, since\nboth a V1 chain id and a CAIP-2 chain id may themselves contain `:` — e.g.\n`(eip155:1, 0xab)` and `(eip155, 1:0xab)` would otherwise collide.\n","readmeFilename":"README.md"}