{"_id":"@atom-circuit/embed-sdk","_rev":"24-e07732393f91cf5ade2657c011a72b82","name":"@atom-circuit/embed-sdk","dist-tags":{"latest":"2.3.1"},"versions":{"1.2.1":{"name":"@atom-circuit/embed-sdk","version":"1.2.1","keywords":["cosmos","atom","swap","widget","embed","skip","iframe","keplr","leap","cosmostation","validator","referral","staking","defi","cosmwasm","react-component"],"license":"MIT","_id":"@atom-circuit/embed-sdk@1.2.1","maintainers":[{"name":"alagiz","email":"artem.alagizov@gmail.com"}],"homepage":"https://github.com/cosmosrescue/atom-circuit-embed-sdk#readme","bugs":{"url":"https://github.com/cosmosrescue/atom-circuit-embed-sdk/issues"},"dist":{"shasum":"80194329115ad1b7da01b118c390c4d7518265aa","tarball":"https://registry.npmjs.org/@atom-circuit/embed-sdk/-/embed-sdk-1.2.1.tgz","fileCount":19,"integrity":"sha512-tLyHcuOwoe8jC9N+KBsOR0cbyatoPSagw2V95wufUyh1nxtmDBDQMBcf0SzLbztPrNj8mDlppd0b18G6kbKI0A==","signatures":[{"sig":"MEUCIB+sZ2m+pyfbuynLe2RskZUQd68oafhV3Y1SNFtrnivLAiEA+gCiXswlOjDekMoadg+lwjUUCDGMqyPYg8wHuk2IX+I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@atom-circuit%2fembed-sdk@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":689782},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./react":{"import":{"types":"./dist/react.d.ts","default":"./dist/react.mjs"},"require":{"types":"./dist/react.d.cts","default":"./dist/react.cjs"}}},"gitHead":"a150f94b348b587957cadd7443ea84ca21e8df42","scripts":{"size":"size-limit","test":"vitest run","build":"tsup","test:e2e":"playwright test","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:978fa4c1-f7ef-4f17-99ec-3e72dde35fc2"}},"repository":{"url":"git+https://github.com/cosmosrescue/atom-circuit-embed-sdk.git","type":"git"},"size-limit":[{"gzip":true,"name":"iife (gzip)","path":"dist/atom-circuit.iife.js","limit":"25 KB"},{"gzip":true,"name":"esm (gzip)","path":"dist/index.mjs","limit":"25 KB"}],"_npmVersion":"11.16.0","description":"Embed the Atom Circuit swap widget on any website with one line. Carries a referralId so swap fees route to the host validator.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{"penpal":"~7.0.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.2.4","jsdom":"^29.1.1","react":"^18.3.1","vitest":"^4.1.7","react-dom":"^18.3.1","size-limit":"^12.1.0","typescript":"^6.0.3","@types/node":"^25.9.1","@types/react":"^18.3.3","@playwright/test":"^1.46.0","@types/react-dom":"^18.3.0","@testing-library/react":"^16.0.0","@size-limit/preset-small-lib":"^12.1.0"},"peerDependencies":{"react":">=17 <20","react-dom":">=17 <20"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/embed-sdk_1.2.1_1780081822724_0.8081806021287075","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@atom-circuit/embed-sdk","version":"1.2.2","keywords":["cosmos","atom","swap","widget","embed","skip","iframe","keplr","leap","cosmostation","validator","referral","staking","defi","cosmwasm","react-component"],"license":"MIT","_id":"@atom-circuit/embed-sdk@1.2.2","maintainers":[{"name":"alagiz","email":"artem.alagizov@gmail.com"}],"homepage":"https://github.com/cosmosrescue/atom-circuit-embed-sdk#readme","bugs":{"url":"https://github.com/cosmosrescue/atom-circuit-embed-sdk/issues"},"dist":{"shasum":"3a395bde61b48a641b668103113139a8beffd1fc","tarball":"https://registry.npmjs.org/@atom-circuit/embed-sdk/-/embed-sdk-1.2.2.tgz","fileCount":19,"integrity":"sha512-sMJA600k7T/r0m3PjUy5QUQpZEKYJq+RuKv+bXd6sTN9t5Yu150qcJXucE9ZA+q4gbZi2gdmvlZIvKr7asuNPg==","signatures":[{"sig":"MEUCICUOH3oxEpiP/pUpP0cvbsFsO4GXaPqVdxETovqdWt4VAiEAkIfSuLeCN1GWZByWgpqYJyKF5p5dowz7bUEL/8P0U5o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@atom-circuit%2fembed-sdk@1.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":685195},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./react":{"import":{"types":"./dist/react.d.ts","default":"./dist/react.mjs"},"require":{"types":"./dist/react.d.cts","default":"./dist/react.cjs"}}},"gitHead":"496239befb44be0cac6217488e3e110efd9c430e","scripts":{"size":"size-limit","test":"vitest run","build":"tsup","test:e2e":"playwright test","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:978fa4c1-f7ef-4f17-99ec-3e72dde35fc2"}},"repository":{"url":"git+https://github.com/cosmosrescue/atom-circuit-embed-sdk.git","type":"git"},"size-limit":[{"gzip":true,"name":"iife (gzip)","path":"dist/atom-circuit.iife.js","limit":"25 KB"},{"gzip":true,"name":"esm (gzip)","path":"dist/index.mjs","limit":"25 KB"}],"_npmVersion":"11.16.0","description":"Embed the Atom Circuit swap widget on any website with one line. Carries a referralId so swap fees route to the host validator.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{"penpal":"~7.0.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.2.4","jsdom":"^29.1.1","react":"^18.3.1","vitest":"^4.1.7","react-dom":"^18.3.1","size-limit":"^12.1.0","typescript":"^6.0.3","@types/node":"^25.9.1","@types/react":"^18.3.3","@playwright/test":"^1.46.0","@types/react-dom":"^18.3.0","@testing-library/react":"^16.0.0","@size-limit/preset-small-lib":"^12.1.0"},"peerDependencies":{"react":">=17 <20","react-dom":">=17 <20"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/embed-sdk_1.2.2_1780380790934_0.08676241751382063","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@atom-circuit/embed-sdk","version":"1.3.0","keywords":["cosmos","atom","swap","widget","embed","skip","iframe","keplr","leap","cosmostation","validator","referral","staking","defi","cosmwasm","react-component"],"license":"MIT","_id":"@atom-circuit/embed-sdk@1.3.0","maintainers":[{"name":"alagiz","email":"artem.alagizov@gmail.com"}],"homepage":"https://github.com/cosmosrescue/atom-circuit-embed-sdk#readme","bugs":{"url":"https://github.com/cosmosrescue/atom-circuit-embed-sdk/issues"},"dist":{"shasum":"144d3f963acf4de7bf8df237de5c97aa5aae2767","tarball":"https://registry.npmjs.org/@atom-circuit/embed-sdk/-/embed-sdk-1.3.0.tgz","fileCount":19,"integrity":"sha512-BgeaF+1ZHbycXK1rDnDPhSd+5TyZDTYACBGZETXBSIPZBx+GK6yRourhlta7hq1aS/rwNuMyUJVmYIV2F6mEzA==","signatures":[{"sig":"MEQCIDhzPzVk+beOAPfLOOjH1hIbrO0wxqKxURCYUOm4gjMDAiBvCOXanoAxy3yXxghAuxk77ntCfd4OpXFXFh9XaiUadA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@atom-circuit%2fembed-sdk@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":711960},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./react":{"import":{"types":"./dist/react.d.ts","default":"./dist/react.mjs"},"require":{"types":"./dist/react.d.cts","default":"./dist/react.cjs"}}},"gitHead":"cc661c30e4a9f1420cddc967fedb5f9e38d09ef0","scripts":{"size":"size-limit","test":"vitest run","build":"tsup","test:e2e":"playwright test","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:978fa4c1-f7ef-4f17-99ec-3e72dde35fc2"}},"repository":{"url":"git+https://github.com/cosmosrescue/atom-circuit-embed-sdk.git","type":"git"},"size-limit":[{"gzip":true,"name":"iife (gzip)","path":"dist/atom-circuit.iife.js","limit":"25 KB"},{"gzip":true,"name":"esm (gzip)","path":"dist/index.mjs","limit":"25 KB"}],"_npmVersion":"11.16.0","description":"Embed the Atom Circuit swap widget on any website with one line. Carries a referralId so swap fees route to the host validator.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{"penpal":"~7.0.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.2.4","jsdom":"^29.1.1","react":"^18.3.1","vitest":"^4.1.7","react-dom":"^18.3.1","size-limit":"^12.1.0","typescript":"^6.0.3","@types/node":"^25.9.1","@types/react":"^18.3.3","@playwright/test":"^1.46.0","@types/react-dom":"^18.3.0","@testing-library/react":"^16.0.0","@size-limit/preset-small-lib":"^12.1.0"},"peerDependencies":{"react":">=17 <20","react-dom":">=17 <20"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/embed-sdk_1.3.0_1780413268483_0.2655838640457058","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@atom-circuit/embed-sdk","version":"2.1.0","keywords":["cosmos","atom","swap","widget","embed","skip","iframe","keplr","leap","cosmostation","validator","referral","staking","defi","cosmwasm","react-component"],"license":"MIT","_id":"@atom-circuit/embed-sdk@2.1.0","maintainers":[{"name":"alagiz","email":"artem.alagizov@gmail.com"}],"homepage":"https://github.com/cosmosrescue/atom-circuit-embed-sdk#readme","bugs":{"url":"https://github.com/cosmosrescue/atom-circuit-embed-sdk/issues"},"dist":{"shasum":"aa61033afbdcf6a25e7771070f71f82f35b07fe8","tarball":"https://registry.npmjs.org/@atom-circuit/embed-sdk/-/embed-sdk-2.1.0.tgz","fileCount":19,"integrity":"sha512-AZrIrqS5oJwi2kXBQXhwWj1IKH+AFHvEL4lEaBAbnSRvnTQJRPWn8/91bdt/f0O1gMHY2FlBV1JTK2fQTaddhA==","signatures":[{"sig":"MEQCIDc9lYuEAN2AX4A/69P9H7ePJBduxo4YRB1m7/SVIOn3AiB727CSxMxpOqbL4RQJuP5V9dvqp2GXamKAWFE7CZBItw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@atom-circuit%2fembed-sdk@2.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1437143},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./react":{"import":{"types":"./dist/react.d.ts","default":"./dist/react.mjs"},"require":{"types":"./dist/react.d.cts","default":"./dist/react.cjs"}}},"gitHead":"7d2f950ca813fc094f5646bb49d3c952f4701142","scripts":{"size":"size-limit","test":"vitest run","build":"tsup","test:e2e":"playwright test","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:978fa4c1-f7ef-4f17-99ec-3e72dde35fc2"}},"repository":{"url":"git+https://github.com/cosmosrescue/atom-circuit-embed-sdk.git","type":"git"},"size-limit":[{"gzip":true,"name":"iife (gzip)","path":"dist/atom-circuit.iife.js","limit":"25 KB"},{"gzip":true,"name":"esm (gzip)","path":"dist/index.mjs","limit":"25 KB"}],"_npmVersion":"11.16.0","description":"Embed the Atom Circuit swap widget on any website with one line. Carries a referralId so swap fees route to the host validator.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{"penpal":"~7.0.6","@dao-dao/cosmiframe":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.2.4","jsdom":"^29.1.1","react":"^18.3.1","vitest":"^4.1.7","react-dom":"^18.3.1","size-limit":"^12.1.0","typescript":"^6.0.3","@types/node":"^25.9.1","@types/react":"^18.3.3","@playwright/test":"^1.46.0","@types/react-dom":"^18.3.0","@testing-library/react":"^16.0.0","@size-limit/preset-small-lib":"^12.1.0"},"peerDependencies":{"react":">=17 <20","react-dom":">=17 <20"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/embed-sdk_2.1.0_1780579804001_0.27383868636941355","host":"s3://npm-registry-packages-npm-production"}},"2.2.0":{"name":"@atom-circuit/embed-sdk","version":"2.2.0","keywords":["cosmos","atom","swap","widget","embed","skip","iframe","keplr","leap","cosmostation","validator","referral","staking","defi","cosmwasm","react-component"],"license":"MIT","_id":"@atom-circuit/embed-sdk@2.2.0","maintainers":[{"name":"alagiz","email":"artem.alagizov@gmail.com"}],"homepage":"https://github.com/cosmosrescue/atom-circuit-embed-sdk#readme","bugs":{"url":"https://github.com/cosmosrescue/atom-circuit-embed-sdk/issues"},"dist":{"shasum":"2c0cef24483043444b8b08bf0d7ee3da4358a0cd","tarball":"https://registry.npmjs.org/@atom-circuit/embed-sdk/-/embed-sdk-2.2.0.tgz","fileCount":19,"integrity":"sha512-7oWwOyDwftidvo5Wlt4ZY1DGy7T8GLiQYHJzcE0ZJK1a9M4S2Phd6hELX1YzQltf065WAjy4/OXbqSZ3F5XQKA==","signatures":[{"sig":"MEQCIGjU651RbJZG84EnWh6dASDB2FwrCbdWITmZjlsSj8REAiA19kHZ1vlOiezD3n7+hpvc2FbK0HKkbTXhUZ8J1KNSWw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@atom-circuit%2fembed-sdk@2.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":1453139},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./react":{"import":{"types":"./dist/react.d.ts","default":"./dist/react.mjs"},"require":{"types":"./dist/react.d.cts","default":"./dist/react.cjs"}}},"gitHead":"076ff730dcb290a4335bfd3945dfc6bf871f2ad0","scripts":{"size":"size-limit","test":"vitest run","build":"tsup","test:e2e":"playwright test","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:978fa4c1-f7ef-4f17-99ec-3e72dde35fc2"}},"repository":{"url":"git+https://github.com/cosmosrescue/atom-circuit-embed-sdk.git","type":"git"},"size-limit":[{"gzip":true,"name":"iife (gzip)","path":"dist/atom-circuit.iife.js","limit":"25 KB"},{"gzip":true,"name":"esm (gzip)","path":"dist/index.mjs","limit":"25 KB"}],"_npmVersion":"11.16.0","description":"Embed the Atom Circuit swap widget on any website with one line. Carries a referralId so swap fees route to the host validator.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","dependencies":{"penpal":"~7.0.6","@dao-dao/cosmiframe":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.2.4","jsdom":"^29.1.1","react":"^18.3.1","vitest":"^4.1.7","react-dom":"^18.3.1","size-limit":"^12.1.0","typescript":"^6.0.3","@types/node":"^25.9.1","@types/react":"^18.3.3","@playwright/test":"^1.46.0","@types/react-dom":"^18.3.0","@testing-library/react":"^16.0.0","@size-limit/preset-small-lib":"^12.1.0"},"peerDependencies":{"react":">=17 <20","react-dom":">=17 <20"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/embed-sdk_2.2.0_1780641825957_0.36336294806211544","host":"s3://npm-registry-packages-npm-production"}},"2.3.1":{"name":"@atom-circuit/embed-sdk","version":"2.3.1","description":"Embed the Atom Circuit swap widget on any website with one line. Carries a referralId so swap fees route to the host validator.","license":"MIT","type":"module","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./react":{"import":{"types":"./dist/react.d.ts","default":"./dist/react.mjs"},"require":{"types":"./dist/react.d.cts","default":"./dist/react.cjs"}}},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","test:e2e":"playwright test","typecheck":"tsc --noEmit","size":"size-limit","prepublishOnly":"npm run build && npm test"},"keywords":["cosmos","atom","swap","widget","embed","skip","iframe","keplr","leap","cosmostation","validator","referral","staking","defi","cosmwasm","react-component"],"repository":{"type":"git","url":"git+https://github.com/cosmosrescue/atom-circuit-embed-sdk.git"},"bugs":{"url":"https://github.com/cosmosrescue/atom-circuit-embed-sdk/issues"},"homepage":"https://github.com/cosmosrescue/atom-circuit-embed-sdk#readme","publishConfig":{"access":"public"},"dependencies":{"@dao-dao/cosmiframe":"^1.0.0","penpal":"~7.0.6"},"peerDependencies":{"react":">=17 <20","react-dom":">=17 <20"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"devDependencies":{"@playwright/test":"^1.46.0","@size-limit/preset-small-lib":"^12.1.0","@testing-library/react":"^16.0.0","@types/node":"^25.9.1","@types/react":"^18.3.3","@types/react-dom":"^18.3.0","jsdom":"^29.1.1","react":"^18.3.1","react-dom":"^18.3.1","size-limit":"^12.1.0","tsup":"^8.2.4","typescript":"^6.0.3","vitest":"^4.1.7"},"engines":{"node":">=20"},"size-limit":[{"name":"iife (gzip)","path":"dist/atom-circuit.iife.js","limit":"25 KB","gzip":true},{"name":"esm (gzip)","path":"dist/index.mjs","limit":"25 KB","gzip":true}],"gitHead":"371187ba5c3603d1ec56cab9c932b84a9fa07912","_id":"@atom-circuit/embed-sdk@2.3.1","_nodeVersion":"24.16.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-gBdtANIhIPrXLEKcM05HDKWfIwTV2Q5mQ6vJk/FLwaOAj+mD2whiNyC5nw+f1pwx/LJREdm9obAAbS5LRpnk+A==","shasum":"8aa13a49a82b3bef156a8541b28b19fbbda4068c","tarball":"https://registry.npmjs.org/@atom-circuit/embed-sdk/-/embed-sdk-2.3.1.tgz","fileCount":19,"unpackedSize":1504355,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@atom-circuit%2fembed-sdk@2.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDfEyCS7W5OKdxYMN3DoaQfgXKbFceg/qMDvhUwaqv9RAIhAM6VgJ41bg388R+aEq/5DZmOEymJfuz3/OTIbQDThaV3"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:978fa4c1-f7ef-4f17-99ec-3e72dde35fc2"}},"directories":{},"maintainers":[{"name":"alagiz","email":"artem.alagizov@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/embed-sdk_2.3.1_1780678023108_0.9663494381572295"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-27T18:03:06.277Z","modified":"2026-06-05T16:47:03.693Z","0.1.0":"2026-05-27T18:03:06.624Z","1.0.0":"2026-05-28T10:08:08.699Z","1.0.1":"2026-05-28T11:04:13.682Z","1.1.0":"2026-05-28T12:03:07.262Z","1.1.1":"2026-05-28T12:07:07.533Z","1.2.0":"2026-05-29T19:00:33.436Z","1.2.1":"2026-05-29T19:10:22.910Z","1.2.2":"2026-06-02T06:13:11.074Z","1.3.0":"2026-06-02T15:14:28.614Z","2.0.0":"2026-06-04T09:22:27.852Z","2.0.1":"2026-06-04T10:52:32.976Z","2.1.0":"2026-06-04T13:30:04.146Z","2.2.0":"2026-06-05T06:43:46.178Z","2.3.0":"2026-06-05T16:14:06.864Z","2.3.1":"2026-06-05T16:47:03.351Z"},"bugs":{"url":"https://github.com/cosmosrescue/atom-circuit-embed-sdk/issues"},"license":"MIT","homepage":"https://github.com/cosmosrescue/atom-circuit-embed-sdk#readme","keywords":["cosmos","atom","swap","widget","embed","skip","iframe","keplr","leap","cosmostation","validator","referral","staking","defi","cosmwasm","react-component"],"repository":{"type":"git","url":"git+https://github.com/cosmosrescue/atom-circuit-embed-sdk.git"},"description":"Embed the Atom Circuit swap widget on any website with one line. Carries a referralId so swap fees route to the host validator.","maintainers":[{"name":"alagiz","email":"artem.alagizov@gmail.com"}],"readme":"# @atom-circuit/embed-sdk\n\nEmbed the [Atom Circuit](https://atomcircuit.net) swap widget on any website. Every swap routed through the widget carries a `referralId` so the 0.5% affiliate fee is converted to ATOM and staked to a Cosmos Hub validator chosen by the host site.\n\n- License: MIT\n- Bundles: ESM, CJS, IIFE\n- Release notes: [CHANGELOG.md](./CHANGELOG.md).\n\n## Install\n\nFor React, Next.js, or any bundled project:\n\n```sh\nnpm install @atom-circuit/embed-sdk\n```\n\nFor static sites that do not bundle, load the IIFE from a CDN with a pinned Subresource Integrity hash:\n\n```html\n<script\n  src=\"https://unpkg.com/@atom-circuit/embed-sdk@2.3.1/dist/atom-circuit.iife.js\"\n  integrity=\"sha384-HupUMMdBD4mVAOQeYUZ7sf4KC7HWmOKwNC3l4kuOQ7/ATqOWx751/x4rdJQp/mly\"\n  crossorigin=\"anonymous\"\n></script>\n```\n\nEach release publishes its hash on the [GitHub release page](https://github.com/cosmosrescue/atom-circuit-embed-sdk/releases). Bump the version pin and the `integrity` value together. Recipe for computing the hash yourself is under [Security](#security).\n\n## Getting your referral ID\n\nOpen your validator page on [atomcircuit.net](https://atomcircuit.net). The referral ID is shown next to your referral link with a Copy button. Either the raw referral ID or your registered validator slug works as `referralId`; both resolve to the same on-chain validator.\n\nIf you do not represent a validator (community sites, ecosystem aggregators, content creators, podcast hosts) you can still embed the widget. Use `referralId: 'general'` to split the affiliate fee equally across all participating validators (registered Atom Circuit validators that have received at least one swap attribution). `referralId` is optional - omit it and the SDK defaults to `'general'`, so the minimal install is one `mount()` call with no options.\n\n## Quick start\n\nPick the stack you ship with. Replace `YOUR_REFERRAL_ID` with the value from your validator profile (or the literal string `general`). Every other field is optional.\n\n### Vanilla HTML\n\n```html\n<div id=\"atom-circuit-widget\"></div>\n<script src=\"https://unpkg.com/@atom-circuit/embed-sdk@2.3.1/dist/atom-circuit.iife.js\"></script>\n<script>\n  AtomCircuit.mount(document.getElementById('atom-circuit-widget'), {\n    referralId: 'YOUR_REFERRAL_ID',\n  });\n</script>\n```\n\nFor production, use the SRI-pinned form from [Install](#install).\n\n### React\n\n```tsx\nimport { AtomCircuitSwap } from '@atom-circuit/embed-sdk/react';\n\nexport function SwapPanel() {\n  return <AtomCircuitSwap referralId=\"YOUR_REFERRAL_ID\" />;\n}\n```\n\n### Next.js (App Router)\n\nThe SDK is iframe-only at runtime; skip the server bundle with `next/dynamic`:\n\n```tsx\n'use client';\nimport dynamic from 'next/dynamic';\n\nconst AtomCircuitSwap = dynamic(\n  () => import('@atom-circuit/embed-sdk/react').then((m) => m.AtomCircuitSwap),\n  {\n    ssr: false,\n    // Reserve the widget's space while the client chunk loads so the page does\n    // not shift when the iframe mounts. Match this to your `minHeight`.\n    loading: () => <div style={{ minHeight: 520 }} />,\n  }\n);\n\nexport default function Page() {\n  return <AtomCircuitSwap referralId=\"YOUR_REFERRAL_ID\" />;\n}\n```\n\nThat is the entire integration: a container plus `referralId`, and the end user connects their wallet inside the widget. Nothing else is required.\n\n`referralId` is the only option that affects where fees go, and even it is optional (omit it and the SDK defaults to `'general'`). Everything else - `theme`, `chrome`, `maxWidth`, `allowReferralChoice`, the callbacks, and the parent-wallet bridge - is optional and additive. You can ship the default embed above and never touch any of them. The rest of this README documents what is configurable and how the trust boundary works. Each stack has a fully-wired example under [`examples/`](./examples/) that shows every option and every callback.\n\n## Supported wallets\n\nWhich wallets the end user can connect with depends on which of the two connect modes you use. Both are fully supported; the difference is only where the wallet lives.\n\n### Built-in in-widget connect (the default)\n\nThis is what you get with a plain embed (no `wallet` option, or `wallet.mode: 'iframe'`): the user connects their wallet inside the widget. The built-in set is fixed:\n\n- **Cosmos:** Keplr and Cosmostation. Each works as a desktop browser extension and on mobile via WalletConnect.\n- **EVM:** any injected browser wallet (MetaMask, Rabby, or anything that exposes `window.ethereum`), plus WalletConnect.\n\n### Parent-wallet reuse (advanced, opt-in)\n\nWhen you opt into parent-wallet mode (`wallet.mode: 'parent'`, see [Reusing the parent page's wallet](#reusing-the-parent-pages-wallet)), the widget reuses whatever wallet is already connected on your page. This is not limited to the built-in set above; it works with any compatible wallet:\n\n- **Cosmos:** any Keplr-API-compatible injected wallet via `fromInjectedCosmosWallet` (any provider exposing `getKey` / `enable` / `getOfflineSigner` / `getOfflineSignerOnlyAmino`), or any connected cosmos-kit wallet client via `fromCosmosKit`. `window.keplr` and `window.cosmostation.providers.keplr` are examples of compatible injected providers, not the only ones; any wallet that implements the same injected API works.\n- **EVM:** any EIP-1193 provider via `fromWagmi` (`window.ethereum`, a wagmi connector's resolved provider, or any object with a `request(...)` method).\n\nThe user always signs in their own wallet UI; keys never leave their wallet. If the bridge cannot be established, the widget silently falls back to the built-in in-widget connect described above, so a swap is always completable.\n\n## Full examples\n\nRunnable example apps live under [`examples/`](./examples/), organized by language and framework, each with its own README:\n\n- TypeScript, React: [examples/typescript/react](./examples/typescript/react)\n- TypeScript, Next.js: [examples/typescript/nextjs](./examples/typescript/nextjs)\n- JavaScript, React: [examples/javascript/react](./examples/javascript/react)\n- JavaScript, Next.js: [examples/javascript/nextjs](./examples/javascript/nextjs)\n- Vanilla HTML: [examples/vanilla](./examples/vanilla)\n\nEach app contains the minimal, full, parent-wallet, and parent-wallet-cosmoskit examples (vanilla covers minimal, full, and parent-wallet).\n\n## API surface\n\n`mount` (vanilla) and `<AtomCircuitSwap />` (React) expose the same options. Exactly one is required:\n\n| Option                   | Required?    | Default     | Purpose                                                              |\n| ------------------------ | ------------ | ----------- | -------------------------------------------------------------------- |\n| `referralId`             | Optional     | `'general'` | Which validator the affiliate fee stakes to. Omit to split across all participating validators. |\n| `allowReferralChoice`    | Optional     | `false`     | Render a validator picker so the end user can change the validator.  |\n| `autoscale`              | Optional     | `false`     | Scale the whole widget up to fill a wide container. See [Autoscale](#autoscale). |\n| `maxScale`               | Optional     | `1.5`       | Cap for `autoscale`, clamped to `[1.0, 3.0]`. Ignored when `autoscale` is off. |\n| `width` / `maxWidth` / `minHeight` / `padding` | Optional | see [Sizing](#sizing) | Layout of the widget wrapper.                              |\n| `theme`                  | Optional     | dark preset | Color palette and typography. See [Theming](#theming).               |\n| `chrome`                 | Optional     | all visible | Hide individual surfaces (logo, wallet button, validator row, footer). |\n| `onReady` / `onResize` / `onSwapSubmitted` / `onSwapBridging` / `onSwapSuccess` / `onSwapError` / `onError` | Optional | none | Lifecycle and swap callbacks. See [Callbacks](#callbacks). |\n| `wallet`                 | Optional     | `'iframe'`  | Advanced: reuse a wallet already connected on your page. See [Reusing the parent page's wallet](#reusing-the-parent-pages-wallet). |\n\nNo option is required: omit everything and the widget mounts in default mode with `referralId: 'general'`, the end user connecting their own wallet inside the iframe. `referralId` is the one option you will almost always set so the fee stakes to a specific validator. The `wallet` option (parent-wallet reuse) is an advanced opt-in covered last.\n\n### `mount(container, options)`\n\n```ts\nconst { iframe, wrapper, client, destroy } = AtomCircuit.mount(container, {\n  referralId: 'YOUR_REFERRAL_ID',\n  // let the end user pick the validator (default false); referralId is the pre-selected default\n  allowReferralChoice: false,\n  // scale the whole widget up on wide containers (default false); cap at 1.5x\n  autoscale: false,\n  maxScale: 1.5,\n  // sizing - all optional\n  width: '100%',\n  maxWidth: '480px',\n  minHeight: '520px',\n  padding: '16px',\n  // appearance - all optional\n  theme: { mode: 'dark', accentColor: '#7b61ff', radius: 12 },\n  chrome: { logo: true, wallet: true, validator: true, footer: true },\n  // callbacks - all optional\n  onReady:         ({ protocolVersion }) => {},\n  onResize:        ({ height })          => {},\n  onSwapSubmitted: ({ txHash, route })   => {},\n  onSwapBridging:  ({ chainId, explorerLink }) => {},\n  onSwapSuccess:   ({ txHash })          => {},\n  onSwapError:     ({ code, message })   => {},\n  onError:         ({ code, message })   => {},\n});\n```\n\nCall `destroy()` when the host removes the widget from the DOM. The returned `wrapper` is the always-present `<div data-atom-circuit-embed>` containing the iframe and the loading overlay.\n\n### `<AtomCircuitSwap />`\n\nSame options as `mount`, expressed as React props. Re-mounts the iframe only when `referralId`, `origin`, `path`, or `wallet.mode` change (those bake into the iframe URL and cannot be applied to a live iframe). Changing `theme`, `chrome`, `width`, `maxWidth`, `padding`, or `minHeight` after the initial mount has no effect, so a stylistic tweak does not drop the user's wallet session. Changing only the wallet handles (`wallet.cosmos` / `wallet.evm`) does not remount; the component diffs handle identity and drives `setWallet` / `clearWallet` under the hood. To force a re-mount (and accept the wallet session drop), bump a `key=` on the component.\n\n### Letting the user choose the validator\n\nBy default the host site's `referralId` is fixed and the end user cannot change it. Set `allowReferralChoice: true` to render a validator picker inside the widget: your `referralId` becomes the pre-selected default, the user can switch to any participating validator (or clear it to split across all via `general`), and their choice is remembered across reloads. Leaving it `false` (the default) is fully backwards-compatible - the fixed-`referralId` behaviour is unchanged.\n\n### Autoscale\n\nThe widget is designed around a natural width of `480px`. In a container wider than that, the default behaviour leaves the widget at its natural density with the extra space unused, so on a wide layout the form can look small and lost. Set `autoscale: true` to make the embed scale its ENTIRE geometry up proportionally - text, buttons, icons, input fields, and spacing all grow together - so a wide container shows a correspondingly larger, more legible widget instead of a small one floating in empty space.\n\nThe scale factor is `clamp(availableWidth / 480, 1.0, maxScale)`:\n\n- Below `480px` of available width, autoscale does nothing: the widget falls back to the default fluid behaviour and reflows to fit, so it never overflows a narrow container or a mobile viewport. There is no horizontal scrollbar.\n- Between `480px` and `480 * maxScale`, the widget scales up linearly with the available width, filling it edge to edge at the matching scale factor.\n- Past `480 * maxScale`, the widget stops growing and sits centered at `maxScale`, so it never stretches beyond its intended proportions on an ultra-wide container.\n\n`maxScale` (default `1.5`) caps the growth and is clamped to `[1.0, 3.0]`; an out-of-range or non-finite value falls back to `1.5`. Setting `maxScale: 1.0` keeps the widget at its natural size on every container (autoscale on, but no growth). `maxScale` is ignored when `autoscale` is `false`.\n\nLeaving `autoscale` off (the default) is byte-identical to the prior behaviour: no scaling, no layout change. The widget's reported height tracks the scaled content automatically, so the iframe still resizes to fit with no internal scrollbar.\n\n## Reusing the parent page's wallet\n\nThis is an advanced, optional feature. You do not need it for a working embed. By default the embedded widget connects its own wallet inside the iframe with no setup: the end user clicks Connect Wallet in the widget even if your page already has a wallet connected. If that default is fine for you, as it is for most integrators, skip this section.\n\nThe feature exists for one case: your site already runs a Cosmos (cosmos-kit) or EVM (wagmi) wallet and you want to reuse that connection so the user never reconnects inside the widget. Opting in needs no configuration: set `wallet.mode: 'parent'` and pass at least one wallet handle (`cosmos`, `evm`, or both). The widget trusts the page it is embedded in via the browser's unspoofable parent origin, so the bridge works without registering anything. The user keeps signing every transaction in their own wallet UI - keys never leave their wallet, and the iframe only requests signatures.\n\nThis is opt-in and fully backward compatible. Omitting the `wallet` option, or setting `wallet.mode` to `'iframe'` (the default), behaves exactly as before.\n\n### The explicit choice: two modes\n\nThe `wallet.mode` field is a deliberate, documented choice you make per embed:\n\n- `'iframe'` (default): the widget connects its own wallet inside the iframe. No bridge, no handles. This is the prior behaviour and the iframe URL is byte-identical to 1.x.\n- `'parent'`: the widget reuses your page's already-connected wallet over a postMessage bridge. Requires at least one wallet handle (`cosmos`, `evm`, or both). No configuration: the widget trusts its actual embedding origin, which the browser supplies and a page cannot spoof.\n\n### Cosmos (cosmos-kit and other Cosmos wallets)\n\nPass `wallet.cosmos`. The simplest path is the `fromCosmosKit` helper, which adapts a connected cosmos-kit wallet client into the handle the bridge needs. In React, derive the client from `useChain()` and wrap it once the wallet is connected:\n\n```jsx\nimport { useChain } from '@cosmos-kit/react';\nimport { fromCosmosKit } from '@atom-circuit/embed-sdk';\n\nconst { status, chainWallet } = useChain('cosmoshub');\n\n// IMPORTANT: useChain() does NOT return a top-level `client`.\n// The wallet client lives at chainWallet.client, and it only exists AFTER connect.\nconst cosmosClient = chainWallet?.client;\n\nconst cosmos = useMemo(\n  () => (status === 'Connected' && cosmosClient ? fromCosmosKit(cosmosClient) : undefined),\n  [status, cosmosClient]   // key on the client identity - it appears asynchronously after connect\n);\n\nreturn <AtomCircuitSwap referralId=\"...\" wallet={{ mode: 'parent', cosmos }} />;\n```\n\n> **Common mistake:** Do not write `const { client } = useChain(...)`. useChain() has no top-level `client`; it is always undefined, so the widget will never adopt the host wallet. The wallet client is `chainWallet.client`.\n\nWith the imperative `mount()` API the same handle is built from whatever cosmos-kit client you already have:\n\n```ts\nimport { mount, fromCosmosKit } from '@atom-circuit/embed-sdk';\n\n// `client` is your connected cosmos-kit wallet client\n// (e.g. a ChainWallet's `.client`, populated only after connect).\nmount(container, {\n  referralId: 'YOUR_REFERRAL_ID',\n  wallet: {\n    mode: 'parent',\n    // parent mode trusts the embedding page by its own origin; nothing else to set\n    cosmos: fromCosmosKit(client, { metadata: { name: 'My App' } }),\n  },\n});\n```\n\n`fromCosmosKit` reads the client's `getOfflineSignerDirect` / `getOfflineSignerAmino` (falling back to a unified `getOfflineSigner(chainId, signerType)` when that is all the client exposes) and throws at wiring time if the client can produce no signer at all. The Cosmos bridge delegates to [@dao-dao/cosmiframe](https://github.com/DA0-DA0/cosmiframe). It is wallet-agnostic: whatever your cosmos-kit has connected (Keplr, Cosmostation, WalletConnect, etc.) works, and the widget needs no matching wallet package of its own.\n\n#### A raw injected provider (no cosmos-kit): `fromInjectedCosmosWallet`\n\nIf you do not run cosmos-kit but a Keplr-API-compatible wallet is injected on your page, adapt the raw provider with `fromInjectedCosmosWallet`. It works for any wallet exposing the Keplr injected API: `window.keplr`, Cosmostation via `window.cosmostation.providers.keplr`, and any other Keplr-compatible injected provider.\n\n```ts\nimport { mount, fromInjectedCosmosWallet } from '@atom-circuit/embed-sdk';\n\n// window.keplr, or window.cosmostation.providers.keplr, etc.\nconst provider = window.keplr;\nawait provider.enable('cosmoshub-4'); // connect on your page first\n\nmount(container, {\n  referralId: 'YOUR_REFERRAL_ID',\n  wallet: {\n    mode: 'parent',\n    // parent mode trusts the embedding page by its own origin; nothing else to set\n    cosmos: fromInjectedCosmosWallet(provider, { metadata: { name: 'My App' } }),\n  },\n});\n```\n\nA raw injected provider exposes `enable` / `getKey` / `sign*` but lacks `connect`, `getAccount`, and `getSimpleAccount` (cosmos-kit normally derives those from `getKey`). `fromInjectedCosmosWallet` wraps the provider into a valid target: it adds a no-op `connect` (the wallet is already connected on your page) and derives `getAccount` / `getSimpleAccount` from `getKey`. Rule of thumb: `fromCosmosKit` for an actual cosmos-kit client, `fromInjectedCosmosWallet` for a raw injected provider.\n\n`fromInjectedCosmosWallet` requires every source chain a swap may use to already be added in the user's wallet. It does not carry a chain-registry dependency to add chains, so if cosmos-kit tries to add a missing chain it surfaces a clear, actionable error (\"the wallet does not have `<chainId>` added. Add it in your wallet first, or use fromCosmosKit which can add chains.\"). If you need to swap from arbitrary source chains the user may not have added, use `fromCosmosKit` (which forwards the real cosmos-kit client's `addChain`).\n\n`fromKeplr` is a backward-compatible alias of `fromInjectedCosmosWallet` (despite the name it accepts any Keplr-compatible provider, including Cosmostation). Prefer `fromInjectedCosmosWallet` in new code; `fromKeplr` is retained and will be removed in a future major.\n\nIf you are on neither stack, construct the handle object directly:\n\n```ts\nwallet: {\n  mode: 'parent',\n  // parent mode trusts the embedding page by its own origin; nothing else to set\n  cosmos: {\n    target: walletClient,                                  // non-signer methods proxied to this\n    getOfflineSignerDirect: (chainId) => /* OfflineDirectSigner */,\n    getOfflineSignerAmino:  (chainId) => /* OfflineAminoSigner  */,\n    metadata: { name: 'My App', imageUrl: 'https://...' }, // optional\n  },\n}\n```\n\n### EVM (wagmi, window.ethereum, any EIP-1193 provider)\n\nPass `wallet.evm` with an EIP-1193 `provider`. The `fromWagmi` helper takes an already-resolved provider:\n\n```ts\nimport { mount, fromWagmi } from '@atom-circuit/embed-sdk';\n\n// wagmi exposes the provider via the connected connector; resolve it first:\n//   const provider = await getAccount(config).connector.getProvider();\n// window.ethereum (or any { request, on?, removeListener? }) also works directly.\nmount(container, {\n  referralId: 'YOUR_REFERRAL_ID',\n  wallet: {\n    mode: 'parent',\n    // parent mode trusts the embedding page by its own origin; nothing else to set\n    evm: fromWagmi(provider),\n  },\n});\n```\n\n**Reuse one wallet for both channels:** Keplr also exposes an EVM provider at `window.keplr.ethereum`, so a single Keplr wallet can serve both the Cosmos and EVM channels. Pass `fromWagmi(window.keplr.ethereum)` directly, or with wagmi target Keplr through an `injected` connector (Keplr announces via EIP-6963 with rdns `app.keplr`). A bare `injected()` or `window.ethereum` resolves to MetaMask, or whatever owns `window.ethereum`.\n\nThe EVM bridge relays `provider.request(...)` calls to your wallet and forwards its `accountsChanged` / `chainChanged` / `disconnect` events to the widget. `on` / `removeListener` on the provider are optional: when absent the bridge simply relays requests and forwards no push events.\n\nYou can pass both `cosmos` and `evm`; the loader wires only the side(s) you supply.\n\n### Connecting after mount (render now, adopt when the wallet connects)\n\nYou rarely have a connected wallet at the instant you mount the widget. The recommended flow is to render the widget immediately in `'parent'` mode with no handles, then hand the wallet over the moment your user connects on your page. The widget is visible the whole time and adopts the reused wallet with no remount and no reconnect.\n\nVanilla `mount()` returns `setWallet` / `clearWallet` for exactly this:\n\n```ts\nconst widget = mount(container, {\n  referralId: 'YOUR_REFERRAL_ID',\n  wallet: { mode: 'parent' }, // no handles yet\n});\n\n// later, once your user connects on your page:\nwidget.setWallet({ cosmos: fromCosmosKit(client) });\n// or pass both: widget.setWallet({ cosmos, evm });\n\n// when your user disconnects on your page:\nwidget.clearWallet();                 // tear down all bridged channels\n// or a single channel: widget.clearWallet(['cosmos']);\n```\n\n`setWallet` (re)wires the bridge for the given channel(s) and posts the internal `ready` signal so the iframe auto-adopts the wallet; calling it again with a fresh handle re-adopts cleanly (replace semantics per channel). `clearWallet` tears the channel(s) down and reverts the iframe to its in-iframe connect fallback. Both are no-ops unless the embed was mounted with `wallet.mode === 'parent'`.\n\nIn React this is automatic: render `<AtomCircuitSwap wallet={{ mode: 'parent' }} />` first, then pass `wallet.cosmos` / `wallet.evm` on a later render once they exist. The component diffs the handle identity and calls `setWallet` / `clearWallet` for you under the hood, with no remount. Changing `wallet.mode` (it bakes into the iframe URL) does remount; changing only the handles does not.\n\n#### CDN / IIFE build: helpers on the global\n\nThe IIFE build exposes the same wallet helpers on the `AtomCircuit` global, so a CDN integrator does not need a bundler to build handles. `AtomCircuit.mount(...)` returns the same `setWallet` / `clearWallet`, and the helpers are available as `AtomCircuit.fromInjectedCosmosWallet` (aliased `AtomCircuit.fromKeplr`), `AtomCircuit.fromCosmosKit`, and `AtomCircuit.fromWagmi`:\n\n```html\n<script\n  src=\"https://unpkg.com/@atom-circuit/embed-sdk@2.3.1/dist/atom-circuit.iife.js\"\n  integrity=\"sha384-HupUMMdBD4mVAOQeYUZ7sf4KC7HWmOKwNC3l4kuOQ7/ATqOWx751/x4rdJQp/mly\"\n  crossorigin=\"anonymous\"\n></script>\n<script>\n  var widget = AtomCircuit.mount(document.getElementById('atom-circuit-widget'), {\n    referralId: 'YOUR_REFERRAL_ID',\n    wallet: { mode: 'parent' }, // no handles yet\n    onWalletConnectRequest: function (channel) {\n      if (channel === 'cosmos') {\n        // Keplr at window.keplr; Cosmostation at window.cosmostation.providers.keplr\n        var provider = window.keplr;\n        provider.enable(['cosmoshub-4', 'osmosis-1']).then(function () {\n          widget.setWallet({\n            cosmos: AtomCircuit.fromInjectedCosmosWallet(provider, { metadata: { name: 'My App' } }),\n          });\n        });\n      } else {\n        window.ethereum.request({ method: 'eth_requestAccounts' }).then(function () {\n          widget.setWallet({ evm: AtomCircuit.fromWagmi(window.ethereum) });\n        });\n      }\n    },\n  });\n</script>\n```\n\nSee `examples/vanilla/full.html` for the complete copy-pasteable version.\n\n### In-widget connect button (`onWalletConnectRequest` + `connectPrompt`)\n\nIn `'parent'` mode, when a channel is not yet bridged the widget shows a not-connected prompt instead of its own wallet picker (the picker belongs to your page, not the iframe). You decide how that prompt behaves:\n\n- Supply `onWalletConnectRequest(channel)` and the widget renders an actionable Connect button. When the user clicks it, the widget calls your handler with the channel (`'cosmos'` or `'evm'`); you run your own connect flow on the parent page and, on success, call `setWallet` (vanilla) or pass the new handle (React). The widget then adopts it. One handler can service both channels; if a channel is unserviceable, your callback may no-op.\n- Omit `onWalletConnectRequest` and the widget shows a passive text prompt instead of a button. Override the text with `connectPrompt` (e.g. `\"Connect your wallet at the top of the page to swap\"`). When `connectPrompt` is omitted the widget uses a friendly generic default.\n\n```ts\nmount(container, {\n  referralId: 'YOUR_REFERRAL_ID',\n  wallet: { mode: 'parent' },\n  onWalletConnectRequest: (channel) => {\n    // run your own connect UI for `channel`, then on success:\n    //   widget.setWallet({ [channel]: handle });\n    openMyConnectModal(channel);\n  },\n  // or, with no handler, a passive prompt:\n  // connectPrompt: 'Connect your wallet at the top of the page to swap',\n});\n```\n\nBoth are only meaningful when `wallet.mode === 'parent'`. In React the `onWalletConnectRequest` callback identity may change between renders without forcing a remount - the latest one is always the one invoked.\n\n### Graceful fallback\n\nReliability is preferred over convenience. In `'parent'` mode, if the bridge cannot be established for any reason - no wallet is connected on the parent, the wallet is unsupported, or the handshake times out - the widget silently falls back to its own in-iframe connect. The user can always complete a swap.\n\n### Trust model\n\nThe wallet lives on your page (the connected wallet). The iframe builds the swap transaction and requests a signature over `postMessage`; your page relays it to the wallet, which shows its own confirmation UI; the iframe never holds keys or a signer. The user's own wallet confirmation is the authoritative backstop - the values the iframe displays are advisory, because a compromised parent could tamper at the relay layer, so the user should always verify amounts and recipients in their wallet. The front-line control is the per-message origin check: both channels validate `event.origin` and `event.source` on every message, the iframe only talks to its real parent origin (which the browser supplies and a page cannot spoof), and the Cosmos channel is never constructed with a wildcard origin. See [SECURITY.md](./SECURITY.md) for the full bridge trust model.\n\n## Theming\n\nThe host SDK is the trust boundary. The theme passes through strict validation, is serialised as compact JSON, and is forwarded to the iframe as a base64-encoded `?theme=` URL parameter. The iframe decodes the validated subset and applies it as CSS custom properties.\n\n| Key                | Type                          | Controls                                                                 |\n| ------------------ | ----------------------------- | ------------------------------------------------------------------------ |\n| `mode`             | `'light' \\| 'dark' \\| 'auto'` | Which built-in preset to start from. `'dark'` is the default; `'light'` is the light preset; `'auto'` follows the host's system preference. Every token below overrides whichever preset you pick. |\n| `accentColor`      | hex string                    | Primary buttons (Swap, Connect) and active highlights. `#abc` or `#aabbcc`. |\n| `accentForeground` | hex string                    | Text/icon color rendered on top of the accent (e.g. the primary-button label). |\n| `background`       | hex string                    | The widget's outer page background.                                      |\n| `foreground`       | hex string                    | Primary text/foreground color.                                           |\n| `card`             | hex string                    | Convenience bundle. Sets every surface in one shot: card / panel (`--bg-card`), the secondary panel (`--bg-secondary`), the input surface (`--bg-input`), the validator / picker band (`--bg-deep`), and a derived hover shade (`--bg-card-hover`). The more specific `cardSecondary` and `input` tokens override individual tiers on top of this. |\n| `cardSecondary`    | hex string                    | Secondary surface tier: the validator / picker band (`--bg-deep`) and the secondary panel (`--bg-secondary`). Overrides the `card` bundle for those two surfaces only; leaves `--bg-card` and `--bg-input` untouched. |\n| `input`            | hex string                    | Input surface (text / amount inputs, `--bg-input`). Overrides the `card` bundle for the input surface only. |\n| `mutedForeground`  | hex string                    | Muted/secondary text: labels, captions, helper text.                     |\n| `border`           | hex string                    | Border color of inputs, cards, and dividers.                             |\n| `borderFocus`      | hex string                    | Focused/secondary border (focused inputs, emphasized dividers).          |\n| `warning`          | hex string                    | Warning notification color.                                              |\n| `success`          | hex string                    | Success notification color.                                              |\n| `error`            | hex string                    | Error notification color.                                                |\n| `radius`           | number                        | Corner radius in px, 0-64 inclusive.                                     |\n| `fontSize`         | number                        | Base font size in px, 8-32 inclusive. Applied at the iframe document root, so it scales the entire widget (every surface is authored in `rem`), not just one text element. |\n| `fontFamily`       | string                        | CSS font-family; CSS-safe subset, no `<>;{}=()`, no newlines, max 200ch. |\n\nEvery field is optional and every color value must be a hex string (`#RGB` or `#RRGGBB`); other CSS color notations (rgb(), named colors) are rejected so the wire surface stays trivial to validate and free of CSS-injection footguns.\n\n**Presets and overrides.** Pick a preset with `mode` (`'dark'` default or `'light'`), then override individual tokens on top of it. Omitting `mode` and every token gives the dark preset unchanged. The override model is additive: `{ mode: 'light', accentColor: '#7b61ff' }` renders the full light preset with only the accent swapped.\n\n**Surface tiers (`card` / `cardSecondary` / `input`).** `card` is the convenience bundle: it sets the card / panel (`--bg-card`), the secondary panel (`--bg-secondary`), the input surface (`--bg-input`), the validator / picker band (`--bg-deep`), and a derived hover shade (`--bg-card-hover`) in one shot. The two more specific tokens are applied after the bundle and win for their tier: `cardSecondary` overrides the secondary / band surfaces (`--bg-secondary` + `--bg-deep`), and `input` overrides the input surface (`--bg-input`). Use `card` alone for a single flat surface color, then reach for `cardSecondary` / `input` only when you want those tiers to differ. Each is independent: supplying `cardSecondary` or `input` without `card` overrides just that tier and leaves the rest at the dapp default.\n\nIf any single field fails validation the entire theme is dropped and the widget renders with its defaults; the SDK emits one `console.warn` describing the failure. The widget does not download fonts, so use a `fontFamily` already loaded on the host page.\n\nSource: [`src/theme.ts`](./src/theme.ts) for validation, [`src/protocol.ts`](./src/protocol.ts) for the `ThemeOptions` type.\n\n### Chrome toggles\n\nHide individual surfaces inside the embed without restyling:\n\n```ts\nchrome: {\n  logo: false,      // Atom Circuit logo (top-left)\n  wallet: false,    // Connect Wallet button (top-right)\n  validator: false, // \"Fees stake with <moniker>\" badge row\n  footer: false,    // bottom links / help footer\n}\n```\n\nEach flag defaults to `true`. A non-boolean drops the entire `chrome` bundle.\n\n### Sizing\n\n- `width`: any CSS width applied to the iframe. When omitted, the SDK does not set the `width` option at all; the iframe falls back to its built-in `width: 100%` (the iframe element is always created with `width: 100%`). Pass `width` only to override that.\n- `maxWidth`: any CSS max-width applied to the iframe. Default unset (no cap). The form inside the widget fills the iframe, so capping the iframe width with `maxWidth` also caps the form - the form never stretches past `maxWidth` even on a wider viewport.\n- `padding`: applied to the wrapper, not the iframe. Default `'0'`.\n- `minHeight`: starting iframe height before the widget reports its content size. Default `'480px'`.\n\nThe runtime iframe height is managed by the SDK's resize handler and cannot be overridden.\n\n#### `className` / `style` target differently across the two surfaces\n\nThese two props attach to a different element depending on which surface you use, so apply them with the right target in mind:\n\n- Vanilla `mount()`: `className` and `style` are applied to the iframe element.\n- React `<AtomCircuitSwap />`: `className` and `style` are applied to the outer container `<div>` the component renders, not the iframe. (The `[data-atom-circuit-embed]` marker lives on the SDK-managed wrapper nested inside that container, so `[data-atom-circuit-embed] iframe` still resolves to exactly one iframe.)\n\nIn both cases `height` and `width` are managed by the SDK (use the `width` / `maxWidth` / `minHeight` options for sizing) and any `height` / `width` in `style` is ignored.\n\n## Callbacks\n\n| Event             | Fires when                                                                            | Payload                          |\n| ----------------- | ------------------------------------------------------------------------------------- | -------------------------------- |\n| `onReady`         | iframe handshake completes; from here the widget is interactive                       | `{ protocolVersion }`            |\n| `onResize`        | iframe content height changes                                                          | `{ height }` in px               |\n| `onSwapSubmitted` | user signed and the source-chain tx broadcast                                          | `{ txHash, route }`              |\n| `onSwapBridging`  | a multi-step swap's bridge leg is still settling (source tx broadcast, not yet done)   | `{ chainId, explorerLink? }`     |\n| `onSwapSuccess`   | cross-chain delivery confirmed by the indexer                                          | `{ txHash }` (source-chain hash) |\n| `onSwapError`     | swap failed inside the iframe or the wallet rejected the signature                     | `{ code, message }`              |\n| `onError`         | SDK-level failure: handshake timeout, iframe load failure, origin mismatch, protocol  | `{ code, message, cause }`       |\n\n`onSwapBridging` is non-terminal: it fires while a multi-step swap's bridge leg is still in flight (for example a CCTP transfer mid-attestation - the source transaction has broadcast and funds are bridging to the next chain, but the swap is not complete). A later `onSwapSuccess` or `onSwapError` still fires for the same swap. It may fire zero times for single-chain swaps that never bridge. Payload `chainId` is the intermediate chain, and `explorerLink` (when present) deep-links the in-flight bridge leg.\n\n`onError` covers widget bring-up failures; `onSwapError` covers in-flow swap failures. They are separate so a host can wire different UI for each.\n\n`onError` codes are stable strings: `handshake_failed`, `iframe_load_failed`, `origin_mismatch`, `protocol_incompatible`, `unknown`. If `onError` is not supplied, the SDK logs a single `console.warn` and continues. Nothing is thrown.\n\n### Capability negotiation\n\nThe iframe advertises a set of capability strings during the handshake. These are purely informational; they let a host inspect what the iframe supports for diagnostics or logging. They are not a host-callable API: the host surface is `on` / `destroy` / `getHandshake` / `has`, and the widget drives its own swap flow internally. There is no programmatic-submit method on the client.\n\n```ts\nconst result = AtomCircuit.mount(container, {\n  referralId: 'YOUR_REFERRAL_ID',\n  onReady: () => {\n    // Informational only - e.g. log which capabilities the iframe advertised.\n    if (result.client.has('swap.status')) {\n      console.log('widget advertises swap.status events');\n    }\n  },\n});\n```\n\n`client.has(name)` returns `false` before the handshake completes and for any capability the iframe did not advertise. Names are case-sensitive.\n\n## Persisting across route changes\n\nReact Router and most SPA routers unmount route-level components when the visitor navigates away. The default behavior is: visitor lands on `/swap`, the widget mounts, the loading spinner runs, the handshake completes. They navigate to `/about`, the widget unmounts (iframe destroyed). They return to `/swap`, the widget remounts from scratch with a fresh spinner. Their wallet session survives via iframe-side browser storage, but in-progress swap state (selected tokens, typed amounts, fetched route) is lost.\n\nThree patterns to handle this:\n\n### Pattern 1 - React layout hoist (recommended for React SPAs)\n\nMount `<AtomCircuitSwap />` once in a top-level layout that does not unmount across route changes. Toggle CSS visibility per route:\n\n```tsx\n'use client';\nimport { AtomCircuitSwap } from '@atom-circuit/embed-sdk/react';\nimport { usePathname } from 'next/navigation';\n\nexport function PersistentSwap() {\n  const pathname = usePathname();\n  return (\n    <div style={{ display: pathname === '/swap' ? 'block' : 'none' }}>\n      <AtomCircuitSwap referralId=\"YOUR_REFERRAL_ID\" />\n    </div>\n  );\n}\n```\n\nThe widget stays mounted across navigations; only `display` toggles. Both wallet and form state are preserved. Trade-off: the iframe and dapp instance stay in memory on every page.\n\n### Pattern 2 - imperative mount once\n\nUse `AtomCircuit.mount()` directly into a persistent DOM container outside the router-managed area. Show or hide via CSS:\n\n```html\n<div id=\"atom-circuit-widget\" style=\"display: none;\"></div>\n<script src=\"https://unpkg.com/@atom-circuit/embed-sdk@2.3.1/dist/atom-circuit.iife.js\"></script>\n<script>\n  AtomCircuit.mount(document.getElementById('atom-circuit-widget'), {\n    referralId: 'YOUR_REFERRAL_ID',\n  });\n  function showSwap() {\n    document.getElementById('atom-circuit-widget').style.display = 'block';\n  }\n  function hideSwap() {\n    document.getElementById('atom-circuit-widget').style.display = 'none';\n  }\n</script>\n```\n\nThe vanilla `mount()` lifecycle is not tied to React. Same trade-off as Pattern 1: persistent memory cost in exchange for state preservation.\n\n### Pattern 3 - accept the reload\n\nZero extra code. Re-handshake on every visit takes 1-3 seconds with the loading spinner. Appropriate when the swap page is the destination rather than a sidebar - which is how Stripe Elements, Mapbox demos, and most embedded widget previews work.\n\n## Loading state\n\nThe wrapper renders a centered spinner overlay during the iframe handshake (typically 1-3s on a warm cache). The overlay fades out on the first `ready` event and is also dismissed if `onError` fires, so a permanent handshake failure never leaves a forever-spinning state. No flash of blank container while the iframe is fetching the dapp bundle.\n\n## Security\n\nThe widget runs inside a sandboxed iframe served from `atomcircuit.net`. It cannot read or write the host page's DOM, cookies, or storage. All host/iframe traffic goes over `postMessage` with origin validation on both sides.\n\n### Subresource Integrity for CDN consumers\n\nCurrent SRI hash:\n\n```html\n<script\n  src=\"https://unpkg.com/@atom-circuit/embed-sdk@2.3.1/dist/atom-circuit.iife.js\"\n  integrity=\"sha384-HupUMMdBD4mVAOQeYUZ7sf4KC7HWmOKwNC3l4kuOQ7/ATqOWx751/x4rdJQp/mly\"\n  crossorigin=\"anonymous\"\n></script>\n```\n\nVerify the hash yourself:\n\n```sh\ncurl -sL https://unpkg.com/@atom-circuit/embed-sdk@2.3.1/dist/atom-circuit.iife.js \\\n  | openssl dgst -sha384 -binary | openssl base64 -A\n```\n\nEach release publishes a fresh hash on the [GitHub release page](https://github.com/cosmosrescue/atom-circuit-embed-sdk/releases); bump the version pin and the `integrity` value together. See [SECURITY.md](./SECURITY.md) for the disclosure channel and the full trust boundary.\n\n### Sandbox attributes\n\n```\nsandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-forms\"\n```\n\n`allow-same-origin` is required so Keplr can inject `window.keplr`. `allow-popups` and its escape variant let wallet popups (Keplr, Cosmostation) open. `allow-top-navigation` is intentionally omitted to limit clickjacking surface.\n\n### Chrome storage partitioning (115+)\n\nChromium 115+ partitions iframe storage by `(iframe origin, top-level site)`. A user who connected their wallet on `validatorA.com` will need to reconnect on `validatorB.com`; each host gets its own isolated wallet session inside the widget.\n\n## Versioning\n\n- The npm package follows semver. Major bumps signal a breaking change to `mount()` or `<AtomCircuitSwap />`.\n- The iframe wire protocol version (`PROTOCOL_VERSION`) is independent of the npm package version. SDK and iframe negotiate at handshake time; a major mismatch surfaces as `onError` with `code: 'protocol_incompatible'` (the widget does not mount in a broken state). A minor or patch difference within the same major is wire-compatible: the SDK logs a single `console.warn` and the widget still mounts.\n\n## Compatibility\n\n- React: `>=17 <20` (peer dependency, optional).\n- Modern evergreen browsers, ES2020 baseline. Tested: Chromium 115+, Firefox 115+, Safari 16+.\n- Desktop browser extensions (Keplr, Cosmostation) are the primary wallet path. Mobile WalletConnect inside an iframe has documented iOS Safari issues.\n- Node.js `>=20` for development of this package.\n- No GPL or other non-permissive runtime dependencies.\n\n## Cosmiframe coexistence\n\nThe Atom Circuit dapp loads [Cosmiframe](https://github.com/DA0-DA0/cosmiframe) for an unrelated integration. When the embedded widget runs on a host page, Cosmiframe logs `Failed to detect Cosmiframe parent of allowed origin` to the browser console. This is non-blocking noise from the dapp side; the swap widget itself functions normally and your `onReady` / `onSwap*` callbacks fire as expected.\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}