@tempoxyz/id 0.0.0-stage → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -2
- package/dist/App.d.ts +20 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +26 -0
- package/dist/App.js.map +1 -0
- package/dist/app/client/.assetsignore +2 -0
- package/dist/app/client/assets/BRLA-CZvVDNYr.png +0 -0
- package/dist/app/client/assets/CHFAU-DCedc4aH.png +0 -0
- package/dist/app/client/assets/DLUSD-BnRXm3EI.png +0 -0
- package/dist/app/client/assets/PRIME-CiFp2-3e.svg +14 -0
- package/dist/app/client/assets/Pilat-Bold-C1t1eIrF.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Book-CbS8ofT8.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Demi-CADSbPAt.woff2 +0 -0
- package/dist/app/client/assets/Pilat-Regular-Bx8vzE7q.woff2 +0 -0
- package/dist/app/client/assets/USD1-COVcO_PB.svg +30 -0
- package/dist/app/client/assets/YLDS-CRh8Zw0g.svg +3 -0
- package/dist/app/client/assets/ccip-Cq1mMiVl.js +1 -0
- package/dist/app/client/assets/frxUSD-n9pTpinR.svg +1 -0
- package/dist/app/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/app/client/assets/index-B7YJVP00.css +1 -0
- package/dist/app/client/assets/index-UXTxXCLk.js +55 -0
- package/dist/app/client/assets/pathUSD-BvaO6ooS.svg +25 -0
- package/dist/app/client/assets/reset-co-CHrff.css +1 -0
- package/dist/app/client/assets/wYLDS-CaCKDrO-.svg +10 -0
- package/dist/app/db/auth.d.ts +3207 -0
- package/dist/app/db/auth.d.ts.map +1 -0
- package/dist/app/db/auth.js +330 -0
- package/dist/app/db/auth.js.map +1 -0
- package/dist/app/db/schema.d.ts +932 -0
- package/dist/app/db/schema.d.ts.map +1 -0
- package/dist/app/db/schema.js +171 -0
- package/dist/app/db/schema.js.map +1 -0
- package/dist/app/server/.vite/manifest.json +489 -0
- package/dist/app/server/assets/BRLA-CZvVDNYr.png +0 -0
- package/dist/app/server/assets/CHFAU-DCedc4aH.png +0 -0
- package/dist/app/server/assets/DLUSD-BnRXm3EI.png +0 -0
- package/dist/app/server/assets/PRIME-CiFp2-3e.svg +14 -0
- package/dist/app/server/assets/Pilat-Bold-C1t1eIrF.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Book-CbS8ofT8.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Demi-CADSbPAt.woff2 +0 -0
- package/dist/app/server/assets/Pilat-Regular-Bx8vzE7q.woff2 +0 -0
- package/dist/app/server/assets/USD1-COVcO_PB.svg +30 -0
- package/dist/app/server/assets/YLDS-CRh8Zw0g.svg +3 -0
- package/dist/app/server/assets/_tanstack-start-manifest_v-11GtFGrq.js +1 -0
- package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js +2 -0
- package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js.map +1 -0
- package/dist/app/server/assets/authorize-C95F-9E1-CbESJKGU.js +31 -0
- package/dist/app/server/assets/authorize-C95F-9E1-CbESJKGU.js.map +1 -0
- package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js +2 -0
- package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js.map +1 -0
- package/dist/app/server/assets/call-UQamaCKN.js +32 -0
- package/dist/app/server/assets/call-UQamaCKN.js.map +1 -0
- package/dist/app/server/assets/ccip-CbNKFO4n.js +2 -0
- package/dist/app/server/assets/ccip-CbNKFO4n.js.map +1 -0
- package/dist/app/server/assets/compiled-query-Ds2NVcFT.js +2 -0
- package/dist/app/server/assets/compiled-query-Ds2NVcFT.js.map +1 -0
- package/dist/app/server/assets/convert-BIC8n32x.js +2 -0
- package/dist/app/server/assets/convert-BIC8n32x.js.map +1 -0
- package/dist/app/server/assets/cookie-CS900nSP.css +1 -0
- package/dist/app/server/assets/cookie-Cce9CrIP.js +10 -0
- package/dist/app/server/assets/cookie-Cce9CrIP.js.map +1 -0
- package/dist/app/server/assets/core-B1HCXUmx.js +56 -0
- package/dist/app/server/assets/core-B1HCXUmx.js.map +1 -0
- package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js +2 -0
- package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js.map +1 -0
- package/dist/app/server/assets/default-u_dwuiYb-BJJ9PwCi.js +2 -0
- package/dist/app/server/assets/default-u_dwuiYb-BJJ9PwCi.js.map +1 -0
- package/dist/app/server/assets/dist-BxSwugSY.js +1 -0
- package/dist/app/server/assets/dist-CZGFhmQd.js +2 -0
- package/dist/app/server/assets/dist-CZGFhmQd.js.map +1 -0
- package/dist/app/server/assets/dist-Dg3PQqiW.js +15 -0
- package/dist/app/server/assets/dist-Dg3PQqiW.js.map +1 -0
- package/dist/app/server/assets/effect-QlVUlMFu-2tSPDT2b.js +2 -0
- package/dist/app/server/assets/effect-QlVUlMFu-2tSPDT2b.js.map +1 -0
- package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js +2 -0
- package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js.map +1 -0
- package/dist/app/server/assets/factory-ipHlJXZY.js +5 -0
- package/dist/app/server/assets/factory-ipHlJXZY.js.map +1 -0
- package/dist/app/server/assets/frxUSD-n9pTpinR.svg +1 -0
- package/dist/app/server/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/app/server/assets/get-id-field-B0x109VU.js +6 -0
- package/dist/app/server/assets/get-id-field-B0x109VU.js.map +1 -0
- package/dist/app/server/assets/index-CLddUTqr-xpSuLpBt.js +2 -0
- package/dist/app/server/assets/index-CLddUTqr-xpSuLpBt.js.map +1 -0
- package/dist/app/server/assets/index-DZEfthgZ-8Uq5s5Pt.js +2 -0
- package/dist/app/server/assets/index-DZEfthgZ-8Uq5s5Pt.js.map +1 -0
- package/dist/app/server/assets/kysely-adapter-MkHAI9Jk.js +1 -0
- package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js +2 -0
- package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js.map +1 -0
- package/dist/app/server/assets/pathUSD-BvaO6ooS.svg +25 -0
- package/dist/app/server/assets/reset-co-CHrff.css +1 -0
- package/dist/app/server/assets/rolldown-runtime-B0Z9INg1.js +1 -0
- package/dist/app/server/assets/router-CcbyBCI4.css +1 -0
- package/dist/app/server/assets/router-xjZtEeaI.js +7 -0
- package/dist/app/server/assets/router-xjZtEeaI.js.map +1 -0
- package/dist/app/server/assets/schema-check-Cf7QOZZD.js +9 -0
- package/dist/app/server/assets/schema-check-Cf7QOZZD.js.map +1 -0
- package/dist/app/server/assets/schemas-C2lCYmR5.js +2 -0
- package/dist/app/server/assets/schemas-C2lCYmR5.js.map +1 -0
- package/dist/app/server/assets/secp256k1-buM5g4AL.js +2 -0
- package/dist/app/server/assets/secp256k1-buM5g4AL.js.map +1 -0
- package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js +2 -0
- package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js.map +1 -0
- package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js +6 -0
- package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js.map +1 -0
- package/dist/app/server/assets/standard-json-Cg1N07hM.js +2 -0
- package/dist/app/server/assets/standard-json-Cg1N07hM.js.map +1 -0
- package/dist/app/server/assets/standard-json-DY77efq0.js +2 -0
- package/dist/app/server/assets/standard-json-DY77efq0.js.map +1 -0
- package/dist/app/server/assets/standard-json-ig2t0wRt.js +2 -0
- package/dist/app/server/assets/standard-json-ig2t0wRt.js.map +1 -0
- package/dist/app/server/assets/standard-json-t-LNckA6.js +2 -0
- package/dist/app/server/assets/standard-json-t-LNckA6.js.map +1 -0
- package/dist/app/server/assets/standard-openapi-CONmVRl8.js +2 -0
- package/dist/app/server/assets/standard-openapi-CONmVRl8.js.map +1 -0
- package/dist/app/server/assets/start-C63VetBp.js +2 -0
- package/dist/app/server/assets/start-C63VetBp.js.map +1 -0
- package/dist/app/server/assets/sury-CWZTCd75-xt1mWc9f.js +2 -0
- package/dist/app/server/assets/sury-CWZTCd75-xt1mWc9f.js.map +1 -0
- package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js +2 -0
- package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js.map +1 -0
- package/dist/app/server/assets/utils-C4ZXZIZW.js +2 -0
- package/dist/app/server/assets/utils-C4ZXZIZW.js.map +1 -0
- package/dist/app/server/assets/valibot--1zFm7rT-NSoY2xTp.js +2 -0
- package/dist/app/server/assets/valibot--1zFm7rT-NSoY2xTp.js.map +1 -0
- package/dist/app/server/assets/valibot-D_HTw1Gn-CJwWeOUE.js +2 -0
- package/dist/app/server/assets/valibot-D_HTw1Gn-CJwWeOUE.js.map +1 -0
- package/dist/app/server/assets/wYLDS-CaCKDrO-.svg +10 -0
- package/dist/app/server/assets/zod-Bwrt9trS-CV38yPnQ.js +2 -0
- package/dist/app/server/assets/zod-Bwrt9trS-CV38yPnQ.js.map +1 -0
- package/dist/app/server/assets/zod-DSgpEGAE-BvlnBE2L.js +2 -0
- package/dist/app/server/assets/zod-DSgpEGAE-BvlnBE2L.js.map +1 -0
- package/dist/app/server/index.js +574 -0
- package/dist/app/server/index.js.map +1 -0
- package/dist/app/server/wrangler.json +1 -0
- package/dist/cli/Admin.d.ts +38 -0
- package/dist/cli/Admin.d.ts.map +1 -0
- package/dist/cli/Admin.js +62 -0
- package/dist/cli/Admin.js.map +1 -0
- package/dist/cli/Apps.d.ts +9 -0
- package/dist/cli/Apps.d.ts.map +1 -0
- package/dist/cli/Apps.js +36 -0
- package/dist/cli/Apps.js.map +1 -0
- package/dist/cli/Cli.d.ts +14 -0
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +27 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/Project.d.ts +20 -0
- package/dist/cli/Project.d.ts.map +1 -0
- package/dist/cli/Project.js +88 -0
- package/dist/cli/Project.js.map +1 -0
- package/dist/cli/Realms.d.ts +24 -0
- package/dist/cli/Realms.d.ts.map +1 -0
- package/dist/cli/Realms.js +49 -0
- package/dist/cli/Realms.js.map +1 -0
- package/dist/cli/Session.d.ts +85 -0
- package/dist/cli/Session.d.ts.map +1 -0
- package/dist/cli/Session.js +178 -0
- package/dist/cli/Session.js.map +1 -0
- package/dist/cli/User.d.ts +29 -0
- package/dist/cli/User.d.ts.map +1 -0
- package/dist/cli/User.js +39 -0
- package/dist/cli/User.js.map +1 -0
- package/dist/cli/V1.d.ts +35 -0
- package/dist/cli/V1.d.ts.map +1 -0
- package/dist/cli/V1.js +41 -0
- package/dist/cli/V1.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +46 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin/apps/create.d.ts +23 -0
- package/dist/cli/commands/admin/apps/create.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/create.js +89 -0
- package/dist/cli/commands/admin/apps/create.js.map +1 -0
- package/dist/cli/commands/admin/apps/delete.d.ts +14 -0
- package/dist/cli/commands/admin/apps/delete.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/delete.js +41 -0
- package/dist/cli/commands/admin/apps/delete.js.map +1 -0
- package/dist/cli/commands/admin/apps/index.d.ts +5 -0
- package/dist/cli/commands/admin/apps/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/index.js +14 -0
- package/dist/cli/commands/admin/apps/index.js.map +1 -0
- package/dist/cli/commands/admin/apps/list.d.ts +9 -0
- package/dist/cli/commands/admin/apps/list.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/list.js +26 -0
- package/dist/cli/commands/admin/apps/list.js.map +1 -0
- package/dist/cli/commands/admin/apps/rotate-secret.d.ts +16 -0
- package/dist/cli/commands/admin/apps/rotate-secret.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/rotate-secret.js +47 -0
- package/dist/cli/commands/admin/apps/rotate-secret.js.map +1 -0
- package/dist/cli/commands/admin/apps/update.d.ts +20 -0
- package/dist/cli/commands/admin/apps/update.d.ts.map +1 -0
- package/dist/cli/commands/admin/apps/update.js +76 -0
- package/dist/cli/commands/admin/apps/update.js.map +1 -0
- package/dist/cli/commands/admin/index.d.ts +5 -0
- package/dist/cli/commands/admin/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/index.js +13 -0
- package/dist/cli/commands/admin/index.js.map +1 -0
- package/dist/cli/commands/admin/migrate.d.ts +9 -0
- package/dist/cli/commands/admin/migrate.d.ts.map +1 -0
- package/dist/cli/commands/admin/migrate.js +17 -0
- package/dist/cli/commands/admin/migrate.js.map +1 -0
- package/dist/cli/commands/admin/realms/add.d.ts +12 -0
- package/dist/cli/commands/admin/realms/add.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/add.js +42 -0
- package/dist/cli/commands/admin/realms/add.js.map +1 -0
- package/dist/cli/commands/admin/realms/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/index.js +13 -0
- package/dist/cli/commands/admin/realms/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/list.d.ts +13 -0
- package/dist/cli/commands/admin/realms/list.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/list.js +36 -0
- package/dist/cli/commands/admin/realms/list.js.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/passkeys/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/index.js +13 -0
- package/dist/cli/commands/admin/realms/passkeys/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/set.d.ts +16 -0
- package/dist/cli/commands/admin/realms/passkeys/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/passkeys/set.js +46 -0
- package/dist/cli/commands/admin/realms/passkeys/set.js.map +1 -0
- package/dist/cli/commands/admin/realms/privy/index.d.ts +5 -0
- package/dist/cli/commands/admin/realms/privy/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/privy/index.js +13 -0
- package/dist/cli/commands/admin/realms/privy/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/privy/set.d.ts +18 -0
- package/dist/cli/commands/admin/realms/privy/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/privy/set.js +66 -0
- package/dist/cli/commands/admin/realms/privy/set.js.map +1 -0
- package/dist/cli/commands/admin/realms/remove.d.ts +11 -0
- package/dist/cli/commands/admin/realms/remove.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/remove.js +35 -0
- package/dist/cli/commands/admin/realms/remove.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts +15 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.js +42 -0
- package/dist/cli/commands/admin/realms/secp256k1/disable.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts +15 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.js +42 -0
- package/dist/cli/commands/admin/realms/secp256k1/enable.js.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.d.ts +9 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.js +17 -0
- package/dist/cli/commands/admin/realms/secp256k1/index.js.map +1 -0
- package/dist/cli/commands/admin/realms/set.d.ts +16 -0
- package/dist/cli/commands/admin/realms/set.d.ts.map +1 -0
- package/dist/cli/commands/admin/realms/set.js +46 -0
- package/dist/cli/commands/admin/realms/set.js.map +1 -0
- package/dist/cli/commands/admin/rotate-key.d.ts +15 -0
- package/dist/cli/commands/admin/rotate-key.d.ts.map +1 -0
- package/dist/cli/commands/admin/rotate-key.js +46 -0
- package/dist/cli/commands/admin/rotate-key.js.map +1 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +34 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/login.d.ts +12 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +29 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/logout.d.ts +8 -0
- package/dist/cli/commands/logout.d.ts.map +1 -0
- package/dist/cli/commands/logout.js +19 -0
- package/dist/cli/commands/logout.js.map +1 -0
- package/dist/cli/commands/whoami.d.ts +12 -0
- package/dist/cli/commands/whoami.d.ts.map +1 -0
- package/dist/cli/commands/whoami.js +24 -0
- package/dist/cli/commands/whoami.js.map +1 -0
- package/dist/client/Actions.d.ts +101 -0
- package/dist/client/Actions.d.ts.map +1 -0
- package/dist/client/Actions.js +90 -0
- package/dist/client/Actions.js.map +1 -0
- package/dist/client/Auth.d.ts +161 -0
- package/dist/client/Auth.d.ts.map +1 -0
- package/dist/client/Auth.js +113 -0
- package/dist/client/Auth.js.map +1 -0
- package/dist/client/Authorization.d.ts +29 -0
- package/dist/client/Authorization.d.ts.map +1 -0
- package/dist/client/Authorization.js +12 -0
- package/dist/client/Authorization.js.map +1 -0
- package/dist/client/Decorator.d.ts +170 -0
- package/dist/client/Decorator.d.ts.map +1 -0
- package/dist/client/Decorator.js +227 -0
- package/dist/client/Decorator.js.map +1 -0
- package/dist/client/Key.d.ts +85 -0
- package/dist/client/Key.d.ts.map +1 -0
- package/dist/client/Key.js +83 -0
- package/dist/client/Key.js.map +1 -0
- package/dist/client/Pending.d.ts +39 -0
- package/dist/client/Pending.d.ts.map +1 -0
- package/dist/client/Pending.js +12 -0
- package/dist/client/Pending.js.map +1 -0
- package/dist/client/Permissions.d.ts +34 -0
- package/dist/client/Permissions.d.ts.map +1 -0
- package/dist/client/Permissions.js +16 -0
- package/dist/client/Permissions.js.map +1 -0
- package/dist/client/Provider.d.ts +16 -0
- package/dist/client/Provider.d.ts.map +1 -0
- package/dist/client/Provider.js +12 -0
- package/dist/client/Provider.js.map +1 -0
- package/dist/client/Step.d.ts +21 -0
- package/dist/client/Step.d.ts.map +1 -0
- package/dist/client/Step.js +16 -0
- package/dist/client/Step.js.map +1 -0
- package/dist/client/Storage.d.ts +27 -0
- package/dist/client/Storage.d.ts.map +1 -0
- package/dist/client/Storage.js +16 -0
- package/dist/client/Storage.js.map +1 -0
- package/dist/client/TempoAccount.d.ts +40 -0
- package/dist/client/TempoAccount.d.ts.map +1 -0
- package/dist/client/TempoAccount.js +16 -0
- package/dist/client/TempoAccount.js.map +1 -0
- package/dist/client/Tokens.d.ts +25 -0
- package/dist/client/Tokens.d.ts.map +1 -0
- package/dist/client/Tokens.js +12 -0
- package/dist/client/Tokens.js.map +1 -0
- package/dist/client/User.d.ts +21 -0
- package/dist/client/User.d.ts.map +1 -0
- package/dist/client/User.js +12 -0
- package/dist/client/User.js.map +1 -0
- package/dist/client/actions/account.d.ts +25 -0
- package/dist/client/actions/account.d.ts.map +1 -0
- package/dist/client/actions/account.js +34 -0
- package/dist/client/actions/account.js.map +1 -0
- package/dist/client/actions/device.d.ts +53 -0
- package/dist/client/actions/device.d.ts.map +1 -0
- package/dist/client/actions/device.js +79 -0
- package/dist/client/actions/device.js.map +1 -0
- package/dist/client/actions/email.d.ts +84 -0
- package/dist/client/actions/email.d.ts.map +1 -0
- package/dist/client/actions/email.js +63 -0
- package/dist/client/actions/email.js.map +1 -0
- package/dist/client/actions/oauth.d.ts +115 -0
- package/dist/client/actions/oauth.d.ts.map +1 -0
- package/dist/client/actions/oauth.js +105 -0
- package/dist/client/actions/oauth.js.map +1 -0
- package/dist/client/actions/passkey.d.ts +88 -0
- package/dist/client/actions/passkey.d.ts.map +1 -0
- package/dist/client/actions/passkey.js +60 -0
- package/dist/client/actions/passkey.js.map +1 -0
- package/dist/client/actions/provider.d.ts +49 -0
- package/dist/client/actions/provider.d.ts.map +1 -0
- package/dist/client/actions/provider.js +34 -0
- package/dist/client/actions/provider.js.map +1 -0
- package/dist/client/actions/realm.d.ts +24 -0
- package/dist/client/actions/realm.d.ts.map +1 -0
- package/dist/client/actions/realm.js +15 -0
- package/dist/client/actions/realm.js.map +1 -0
- package/dist/client/actions/redirect.d.ts +153 -0
- package/dist/client/actions/redirect.d.ts.map +1 -0
- package/dist/client/actions/redirect.js +236 -0
- package/dist/client/actions/redirect.js.map +1 -0
- package/dist/client/internal/accessKey.d.ts +21 -0
- package/dist/client/internal/accessKey.d.ts.map +1 -0
- package/dist/client/internal/accessKey.js +38 -0
- package/dist/client/internal/accessKey.js.map +1 -0
- package/dist/client/internal/account.d.ts +14 -0
- package/dist/client/internal/account.d.ts.map +1 -0
- package/dist/client/internal/account.js +3 -0
- package/dist/client/internal/account.js.map +1 -0
- package/dist/client/internal/api.d.ts +106 -0
- package/dist/client/internal/api.d.ts.map +1 -0
- package/dist/client/internal/api.js +129 -0
- package/dist/client/internal/api.js.map +1 -0
- package/dist/client/internal/headless.d.ts +33 -0
- package/dist/client/internal/headless.d.ts.map +1 -0
- package/dist/client/internal/headless.js +46 -0
- package/dist/client/internal/headless.js.map +1 -0
- package/dist/client/internal/indexedDb.d.ts +9 -0
- package/dist/client/internal/indexedDb.d.ts.map +1 -0
- package/dist/client/internal/indexedDb.js +32 -0
- package/dist/client/internal/indexedDb.js.map +1 -0
- package/dist/client/internal/request.d.ts +58 -0
- package/dist/client/internal/request.d.ts.map +1 -0
- package/dist/client/internal/request.js +45 -0
- package/dist/client/internal/request.js.map +1 -0
- package/dist/client/internal/store.d.ts +12 -0
- package/dist/client/internal/store.d.ts.map +1 -0
- package/dist/client/internal/store.js +15 -0
- package/dist/client/internal/store.js.map +1 -0
- package/dist/client.d.ts +20 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +20 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/Apps.d.ts +3051 -0
- package/dist/internal/Apps.d.ts.map +1 -0
- package/dist/internal/Apps.js +472 -0
- package/dist/internal/Apps.js.map +1 -0
- package/dist/internal/Auth.d.ts +4058 -0
- package/dist/internal/Auth.d.ts.map +1 -0
- package/dist/internal/Auth.js +137 -0
- package/dist/internal/Auth.js.map +1 -0
- package/dist/internal/Authorize.d.ts +532 -0
- package/dist/internal/Authorize.d.ts.map +1 -0
- package/dist/internal/Authorize.js +326 -0
- package/dist/internal/Authorize.js.map +1 -0
- package/dist/internal/Device.d.ts +371 -0
- package/dist/internal/Device.d.ts.map +1 -0
- package/dist/internal/Device.js +271 -0
- package/dist/internal/Device.js.map +1 -0
- package/dist/internal/Env.d.ts +57 -0
- package/dist/internal/Env.d.ts.map +1 -0
- package/dist/internal/Env.js +2 -0
- package/dist/internal/Env.js.map +1 -0
- package/dist/internal/ErrorResponse.d.ts +609 -0
- package/dist/internal/ErrorResponse.d.ts.map +1 -0
- package/dist/internal/ErrorResponse.js +679 -0
- package/dist/internal/ErrorResponse.js.map +1 -0
- package/dist/internal/Id.d.ts +10 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +34 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/KeyAuthorization.d.ts +1456 -0
- package/dist/internal/KeyAuthorization.d.ts.map +1 -0
- package/dist/internal/KeyAuthorization.js +1030 -0
- package/dist/internal/KeyAuthorization.js.map +1 -0
- package/dist/internal/Limits.d.ts +65 -0
- package/dist/internal/Limits.d.ts.map +1 -0
- package/dist/internal/Limits.js +35 -0
- package/dist/internal/Limits.js.map +1 -0
- package/dist/internal/Log.d.ts +49 -0
- package/dist/internal/Log.d.ts.map +1 -0
- package/dist/internal/Log.js +101 -0
- package/dist/internal/Log.js.map +1 -0
- package/dist/internal/LogLine.d.ts +33 -0
- package/dist/internal/LogLine.d.ts.map +1 -0
- package/dist/internal/LogLine.js +56 -0
- package/dist/internal/LogLine.js.map +1 -0
- package/dist/internal/Migrations.d.ts +19 -0
- package/dist/internal/Migrations.d.ts.map +1 -0
- package/dist/internal/Migrations.js +57 -0
- package/dist/internal/Migrations.js.map +1 -0
- package/dist/internal/Owner.d.ts +146 -0
- package/dist/internal/Owner.d.ts.map +1 -0
- package/dist/internal/Owner.js +65 -0
- package/dist/internal/Owner.js.map +1 -0
- package/dist/internal/Passkey.d.ts +528 -0
- package/dist/internal/Passkey.d.ts.map +1 -0
- package/dist/internal/Passkey.js +658 -0
- package/dist/internal/Passkey.js.map +1 -0
- package/dist/internal/PendingKey.d.ts +49 -0
- package/dist/internal/PendingKey.d.ts.map +1 -0
- package/dist/internal/PendingKey.js +58 -0
- package/dist/internal/PendingKey.js.map +1 -0
- package/dist/internal/Privy.d.ts +105 -0
- package/dist/internal/Privy.d.ts.map +1 -0
- package/dist/internal/Privy.js +224 -0
- package/dist/internal/Privy.js.map +1 -0
- package/dist/internal/RateLimit.d.ts +190 -0
- package/dist/internal/RateLimit.d.ts.map +1 -0
- package/dist/internal/RateLimit.js +148 -0
- package/dist/internal/RateLimit.js.map +1 -0
- package/dist/internal/Realm.d.ts +281 -0
- package/dist/internal/Realm.d.ts.map +1 -0
- package/dist/internal/Realm.js +477 -0
- package/dist/internal/Realm.js.map +1 -0
- package/dist/internal/RequestId.d.ts +16 -0
- package/dist/internal/RequestId.d.ts.map +1 -0
- package/dist/internal/RequestId.js +78 -0
- package/dist/internal/RequestId.js.map +1 -0
- package/dist/internal/SigningKey.d.ts +115 -0
- package/dist/internal/SigningKey.d.ts.map +1 -0
- package/dist/internal/SigningKey.js +197 -0
- package/dist/internal/SigningKey.js.map +1 -0
- package/dist/internal/TestInbox.d.ts +42 -0
- package/dist/internal/TestInbox.d.ts.map +1 -0
- package/dist/internal/TestInbox.js +20 -0
- package/dist/internal/TestInbox.js.map +1 -0
- package/dist/internal/Timing.d.ts +51 -0
- package/dist/internal/Timing.d.ts.map +1 -0
- package/dist/internal/Timing.js +103 -0
- package/dist/internal/Timing.js.map +1 -0
- package/dist/internal/Validation.d.ts +52 -0
- package/dist/internal/Validation.d.ts.map +1 -0
- package/dist/internal/Validation.js +22 -0
- package/dist/internal/Validation.js.map +1 -0
- package/dist/internal/Wallet.d.ts +37 -0
- package/dist/internal/Wallet.d.ts.map +1 -0
- package/dist/internal/Wallet.js +43 -0
- package/dist/internal/Wallet.js.map +1 -0
- package/dist/worker.d.ts +12 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +12 -0
- package/dist/worker.js.map +1 -0
- package/package.json +79 -3
- package/src/Api.ts +151 -0
- package/src/App.ts +56 -0
- package/src/api/account.ts +311 -0
- package/src/api/authenticate.ts +1290 -0
- package/src/api/authorize.ts +1030 -0
- package/src/api/device.ts +874 -0
- package/src/api/health.ts +72 -0
- package/src/api/lib/AccountStep.ts +335 -0
- package/src/api/lib/Auth.ts +134 -0
- package/src/api/lib/Consent.ts +339 -0
- package/src/api/lib/Cors.ts +107 -0
- package/src/api/lib/Database.ts +10 -0
- package/src/api/lib/DeviceRequest.ts +265 -0
- package/src/api/lib/FirstAccount.ts +90 -0
- package/src/api/lib/KeySigner.ts +393 -0
- package/src/api/lib/PasskeyLink.ts +162 -0
- package/src/api/lib/Session.ts +34 -0
- package/src/api/lib/SignInConsent.ts +316 -0
- package/src/api/oauth.ts +1282 -0
- package/src/api/provider.ts +441 -0
- package/src/app/components/Button.tsx +128 -0
- package/src/app/components/CodeInput.tsx +186 -0
- package/src/app/components/ErrorMessage.tsx +66 -0
- package/src/app/components/Grant.tsx +323 -0
- package/src/app/components/Input.tsx +48 -0
- package/src/app/components/Tooltip.tsx +45 -0
- package/src/app/components/icons/BRLA.png +0 -0
- package/src/app/components/icons/BRZ.svg +1 -0
- package/src/app/components/icons/CHFAU.png +0 -0
- package/src/app/components/icons/DLUSD.png +0 -0
- package/src/app/components/icons/EURAU.svg +1 -0
- package/src/app/components/icons/EURC.e.svg +1 -0
- package/src/app/components/icons/GBPA.svg +4 -0
- package/src/app/components/icons/GUSD.svg +1 -0
- package/src/app/components/icons/MACH.svg +4 -0
- package/src/app/components/icons/OUSD.svg +5 -0
- package/src/app/components/icons/PRIME.svg +14 -0
- package/src/app/components/icons/SBC.svg +1 -0
- package/src/app/components/icons/SEKAU.svg +5 -0
- package/src/app/components/icons/USD1.svg +30 -0
- package/src/app/components/icons/USDB.svg +11 -0
- package/src/app/components/icons/USDC.e.svg +1 -0
- package/src/app/components/icons/USDT0.svg +1 -0
- package/src/app/components/icons/USDY.svg +16 -0
- package/src/app/components/icons/USDe.svg +1 -0
- package/src/app/components/icons/YLDS.svg +3 -0
- package/src/app/components/icons/alphaUSD.svg +1 -0
- package/src/app/components/icons/betaUSD.svg +1 -0
- package/src/app/components/icons/cUSD.svg +1 -0
- package/src/app/components/icons/cbBTC.svg +1 -0
- package/src/app/components/icons/frxUSD.svg +1 -0
- package/src/app/components/icons/goUSD.svg +5 -0
- package/src/app/components/icons/iUSD.svg +1 -0
- package/src/app/components/icons/pathUSD.svg +25 -0
- package/src/app/components/icons/rUSD.svg +1 -0
- package/src/app/components/icons/reUSD.svg +1 -0
- package/src/app/components/icons/sUSDe.svg +1 -0
- package/src/app/components/icons/siUSD.svg +1 -0
- package/src/app/components/icons/stcUSD.svg +1 -0
- package/src/app/components/icons/syrupUSDC.svg +5 -0
- package/src/app/components/icons/thetaUSD.svg +1 -0
- package/src/app/components/icons/wYLDS.svg +10 -0
- package/src/app/components/icons/wsrUSD.svg +1 -0
- package/src/app/components/logos/OUSD.dark.svg +17 -0
- package/src/app/components/logos/OUSD.light.svg +17 -0
- package/src/app/crons/cleanup.ts +42 -0
- package/src/app/db/auth.ts +416 -0
- package/src/app/db/migrations/0000_better_auth.sql +53 -0
- package/src/app/db/migrations/0001_oauth_provider.sql +162 -0
- package/src/app/db/migrations/0002_device_code.sql +17 -0
- package/src/app/db/migrations/0003_realms.sql +27 -0
- package/src/app/db/migrations/0004_default_realm.sql +2 -0
- package/src/app/db/migrations/0005_passkeys.sql +30 -0
- package/src/app/db/migrations/0006_first_accounts.sql +9 -0
- package/src/app/db/migrations/0007_pending_keys.sql +13 -0
- package/src/app/db/migrations/0008_secp256k1_owners.sql +18 -0
- package/src/app/db/migrations/0009_device_requests.sql +8 -0
- package/src/app/db/migrations/0010_device_keys.sql +4 -0
- package/src/app/db/migrations/meta/0000_snapshot.json +362 -0
- package/src/app/db/migrations/meta/0001_snapshot.json +1487 -0
- package/src/app/db/migrations/meta/0002_snapshot.json +1603 -0
- package/src/app/db/migrations/meta/0003_snapshot.json +1760 -0
- package/src/app/db/migrations/meta/0004_snapshot.json +1760 -0
- package/src/app/db/migrations/meta/0005_snapshot.json +1911 -0
- package/src/app/db/migrations/meta/0006_snapshot.json +1967 -0
- package/src/app/db/migrations/meta/0007_snapshot.json +2047 -0
- package/src/app/db/migrations/meta/0008_snapshot.json +2157 -0
- package/src/app/db/migrations/meta/0009_snapshot.json +2207 -0
- package/src/app/db/migrations/meta/0010_snapshot.json +2231 -0
- package/src/app/db/migrations/meta/_journal.json +83 -0
- package/src/app/db/schema.ts +218 -0
- package/src/app/env.ts +49 -0
- package/src/app/lib/Client.ts +82 -0
- package/src/app/lib/Loader.ts +24 -0
- package/src/app/package.json +8 -0
- package/src/app/routeTree.gen.ts +198 -0
- package/src/app/router.tsx +48 -0
- package/src/app/routes/[_].flows.tsx +3001 -0
- package/src/app/routes/__root.tsx +91 -0
- package/src/app/routes/authorize.tsx +197 -0
- package/src/app/routes/choose-account.tsx +111 -0
- package/src/app/routes/deposit.tsx +105 -0
- package/src/app/routes/device.tsx +227 -0
- package/src/app/routes/index.tsx +115 -0
- package/src/app/routes/login.tsx +506 -0
- package/src/app/screens/Account.tsx +347 -0
- package/src/app/screens/Approval.tsx +276 -0
- package/src/app/screens/ChooseAccount.tsx +240 -0
- package/src/app/screens/Deposit.tsx +762 -0
- package/src/app/screens/DeviceApproval.tsx +480 -0
- package/src/app/screens/SignIn.tsx +362 -0
- package/src/app/screens/chains/base.svg +3 -0
- package/src/app/screens/chains/ethereum.svg +11 -0
- package/src/app/screens/chains/solana.svg +4 -0
- package/src/app/screens/chains/tempo.svg +4 -0
- package/src/app/server.ts +204 -0
- package/src/app/vite.config.ts +95 -0
- package/src/app/void.config.ts +29 -0
- package/src/app/zyzz.config.ts +274 -0
- package/src/cli/Admin.ts +73 -0
- package/src/cli/Apps.ts +29 -0
- package/src/cli/Cli.ts +42 -0
- package/src/cli/Project.ts +117 -0
- package/src/cli/Realms.ts +50 -0
- package/src/cli/Session.ts +239 -0
- package/src/cli/User.ts +45 -0
- package/src/cli/V1.ts +57 -0
- package/src/cli/bin.ts +44 -0
- package/src/cli/commands/admin/apps/create.ts +101 -0
- package/src/cli/commands/admin/apps/delete.ts +38 -0
- package/src/cli/commands/admin/apps/index.ts +15 -0
- package/src/cli/commands/admin/apps/list.ts +25 -0
- package/src/cli/commands/admin/apps/rotate-secret.ts +47 -0
- package/src/cli/commands/admin/apps/update.ts +86 -0
- package/src/cli/commands/admin/index.ts +14 -0
- package/src/cli/commands/admin/migrate.ts +16 -0
- package/src/cli/commands/admin/realms/add.ts +40 -0
- package/src/cli/commands/admin/realms/index.ts +14 -0
- package/src/cli/commands/admin/realms/list.ts +38 -0
- package/src/cli/commands/admin/realms/passkeys/index.ts +15 -0
- package/src/cli/commands/admin/realms/passkeys/set.ts +44 -0
- package/src/cli/commands/admin/realms/privy/index.ts +14 -0
- package/src/cli/commands/admin/realms/privy/set.ts +69 -0
- package/src/cli/commands/admin/realms/remove.ts +33 -0
- package/src/cli/commands/admin/realms/secp256k1/disable.ts +40 -0
- package/src/cli/commands/admin/realms/secp256k1/enable.ts +40 -0
- package/src/cli/commands/admin/realms/secp256k1/index.ts +19 -0
- package/src/cli/commands/admin/realms/set.ts +46 -0
- package/src/cli/commands/admin/rotate-key.ts +47 -0
- package/src/cli/commands/init.ts +42 -0
- package/src/cli/commands/login.ts +32 -0
- package/src/cli/commands/logout.ts +19 -0
- package/src/cli/commands/whoami.ts +23 -0
- package/src/client/Actions.ts +168 -0
- package/src/client/Auth.ts +285 -0
- package/src/client/Authorization.ts +34 -0
- package/src/client/Decorator.ts +410 -0
- package/src/client/Key.ts +140 -0
- package/src/client/Pending.ts +46 -0
- package/src/client/Permissions.ts +39 -0
- package/src/client/Provider.ts +18 -0
- package/src/client/Step.ts +24 -0
- package/src/client/Storage.ts +29 -0
- package/src/client/TempoAccount.ts +42 -0
- package/src/client/Tokens.ts +27 -0
- package/src/client/User.ts +23 -0
- package/src/client/actions/account.ts +57 -0
- package/src/client/actions/device.ts +151 -0
- package/src/client/actions/email.ts +141 -0
- package/src/client/actions/oauth.ts +182 -0
- package/src/client/actions/passkey.ts +141 -0
- package/src/client/actions/provider.ts +70 -0
- package/src/client/actions/realm.ts +36 -0
- package/src/client/actions/redirect.ts +408 -0
- package/src/client/internal/accessKey.ts +54 -0
- package/src/client/internal/account.ts +15 -0
- package/src/client/internal/api.ts +224 -0
- package/src/client/internal/headless.ts +77 -0
- package/src/client/internal/indexedDb.ts +44 -0
- package/src/client/internal/request.ts +71 -0
- package/src/client/internal/store.ts +20 -0
- package/src/client.ts +19 -0
- package/src/index.ts +6 -0
- package/src/internal/Apps.ts +718 -0
- package/src/internal/Auth.ts +203 -0
- package/src/internal/Authorize.ts +424 -0
- package/src/internal/Balance.ts +168 -0
- package/src/internal/BodyLimit.ts +36 -0
- package/src/internal/Chain.ts +16 -0
- package/src/internal/Device.ts +469 -0
- package/src/internal/Env.ts +58 -0
- package/src/internal/ErrorResponse.ts +854 -0
- package/src/internal/Id.ts +41 -0
- package/src/internal/KeyAuthorization.ts +1339 -0
- package/src/internal/Limits.ts +39 -0
- package/src/internal/Log.ts +178 -0
- package/src/internal/LogLine.ts +87 -0
- package/src/internal/Logout.ts +336 -0
- package/src/internal/Migrations.ts +86 -0
- package/src/internal/OpenApi.ts +300 -0
- package/src/internal/Owner.ts +211 -0
- package/src/internal/Passkey.ts +1052 -0
- package/src/internal/PendingKey.ts +104 -0
- package/src/internal/Privy.ts +402 -0
- package/src/internal/Provider.ts +125 -0
- package/src/internal/RateLimit.ts +259 -0
- package/src/internal/Realm.ts +768 -0
- package/src/internal/RequestId.ts +118 -0
- package/src/internal/SignInGrant.ts +168 -0
- package/src/internal/SigningKey.ts +286 -0
- package/src/internal/TempoAccount.ts +342 -0
- package/src/internal/TestInbox.ts +51 -0
- package/src/internal/Timing.ts +158 -0
- package/src/internal/Validation.ts +52 -0
- package/src/internal/Wallet.ts +62 -0
- package/src/internal/owners/Passkey.ts +72 -0
- package/src/internal/owners/Privy.ts +81 -0
- package/src/internal/owners/Secp256k1.ts +143 -0
- package/src/types/app.d.ts +19 -0
- package/src/worker.ts +11 -0
|
@@ -0,0 +1,1030 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Access keys (TIP-1011) on a user's Tempo Account, for keys that apps hold. A request takes the
|
|
3
|
+
* shape of the Accounts SDK's `wallet_connect` key authorization capability. The user approves it on
|
|
4
|
+
* a page, or it must fit the headless ceiling, and the account's owner signs it. An app that holds
|
|
5
|
+
* the `tempo-id:sign` scope may send a challenge. Tempo ID binds the challenge as the key's witness
|
|
6
|
+
* (TIP-1053), so the owner's one signature covers both.
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { AbiFunction, Address, Hex, PublicKey, Value } from 'ox';
|
|
10
|
+
import { KeyAuthorization, SignatureEnvelope } from 'ox/tempo';
|
|
11
|
+
import { Authentication } from 'ox/webauthn';
|
|
12
|
+
import { hashMessage, zeroAddress } from 'viem';
|
|
13
|
+
import { Account } from 'viem/tempo';
|
|
14
|
+
import { tempo, tempoDevnet, tempoLocalnet, tempoTestnet, } from 'viem/tempo/chains';
|
|
15
|
+
import { ousd as openUsd, tokens } from 'viem/tokens';
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import * as Apps from './Apps.js';
|
|
18
|
+
import * as ErrorResponse from './ErrorResponse.js';
|
|
19
|
+
/** The request carries a challenge, which its app may not bind. */
|
|
20
|
+
export class ChallengeNotPermittedError extends ErrorResponse.define('challenge_not_permitted') {
|
|
21
|
+
name = 'KeyAuthorization.ChallengeNotPermittedError';
|
|
22
|
+
constructor(options) {
|
|
23
|
+
const { clientId } = options;
|
|
24
|
+
super({
|
|
25
|
+
error_description: `Challenge not permitted: the app lacks the \`${Apps.signScope}\` scope. Remove \`challenge\`, or grant the app the scope.`,
|
|
26
|
+
field: 'challenge',
|
|
27
|
+
meta: { client_id: clientId, scope: Apps.signScope },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Two limits name the same token. */
|
|
32
|
+
export class DuplicateLimitError extends ErrorResponse.define('duplicate_limit') {
|
|
33
|
+
name = 'KeyAuthorization.DuplicateLimitError';
|
|
34
|
+
}
|
|
35
|
+
/** Two scopes name the same call on one token. */
|
|
36
|
+
export class DuplicateScopeError extends ErrorResponse.define('duplicate_scope') {
|
|
37
|
+
name = 'KeyAuthorization.DuplicateScopeError';
|
|
38
|
+
}
|
|
39
|
+
/** `limits` is an empty list. */
|
|
40
|
+
export class EmptyLimitsError extends ErrorResponse.define('empty_limits') {
|
|
41
|
+
name = 'KeyAuthorization.EmptyLimitsError';
|
|
42
|
+
}
|
|
43
|
+
/** `scopes` is an empty list. */
|
|
44
|
+
export class EmptyScopesError extends ErrorResponse.define('empty_scopes') {
|
|
45
|
+
name = 'KeyAuthorization.EmptyScopesError';
|
|
46
|
+
}
|
|
47
|
+
/** A headless key lasts longer than a year. */
|
|
48
|
+
export class ExpiryExceedsMaximumError extends ErrorResponse.define('expiry_exceeds_maximum') {
|
|
49
|
+
name = 'KeyAuthorization.ExpiryExceedsMaximumError';
|
|
50
|
+
}
|
|
51
|
+
/** The key expiry is in the past. */
|
|
52
|
+
export class ExpiryPassedError extends ErrorResponse.define('expiry_passed') {
|
|
53
|
+
name = 'KeyAuthorization.ExpiryPassedError';
|
|
54
|
+
}
|
|
55
|
+
/** The key chain ID is 0. */
|
|
56
|
+
export class InvalidChainError extends ErrorResponse.define('invalid_chain') {
|
|
57
|
+
name = 'KeyAuthorization.InvalidChainError';
|
|
58
|
+
}
|
|
59
|
+
/** The key expiry is 0, which never expires. */
|
|
60
|
+
export class InvalidExpiryError extends ErrorResponse.define('invalid_expiry') {
|
|
61
|
+
name = 'KeyAuthorization.InvalidExpiryError';
|
|
62
|
+
}
|
|
63
|
+
/** A limit's `period` is not a whole number of seconds. */
|
|
64
|
+
export class InvalidPeriodError extends ErrorResponse.define('invalid_period') {
|
|
65
|
+
name = 'KeyAuthorization.InvalidPeriodError';
|
|
66
|
+
}
|
|
67
|
+
/** The key public key is not a valid point. */
|
|
68
|
+
export class InvalidPublicKeyError extends ErrorResponse.define('invalid_public_key') {
|
|
69
|
+
name = 'KeyAuthorization.InvalidPublicKeyError';
|
|
70
|
+
}
|
|
71
|
+
/** A scope's `recipients` names the zero address, or one address twice. */
|
|
72
|
+
export class InvalidRecipientsError extends ErrorResponse.define('invalid_recipients') {
|
|
73
|
+
name = 'KeyAuthorization.InvalidRecipientsError';
|
|
74
|
+
}
|
|
75
|
+
/** A headless key limit exceeds the token’s ceiling. */
|
|
76
|
+
export class LimitExceedsMaximumError extends ErrorResponse.define('limit_exceeds_maximum') {
|
|
77
|
+
name = 'KeyAuthorization.LimitExceedsMaximumError';
|
|
78
|
+
}
|
|
79
|
+
/** The key authorization names no key. */
|
|
80
|
+
export class MissingKeyError extends ErrorResponse.define('missing_key') {
|
|
81
|
+
name = 'KeyAuthorization.MissingKeyError';
|
|
82
|
+
}
|
|
83
|
+
/** An `approve` scope names no spenders. */
|
|
84
|
+
export class MissingRecipientsError extends ErrorResponse.define('missing_recipients') {
|
|
85
|
+
name = 'KeyAuthorization.MissingRecipientsError';
|
|
86
|
+
}
|
|
87
|
+
/** A scope calls a token no limit names. */
|
|
88
|
+
export class ScopeWithoutLimitError extends ErrorResponse.define('scope_without_limit') {
|
|
89
|
+
name = 'KeyAuthorization.ScopeWithoutLimitError';
|
|
90
|
+
}
|
|
91
|
+
/** A scope calls a function a key may not call. */
|
|
92
|
+
export class UnsupportedCallError extends ErrorResponse.define('unsupported_call') {
|
|
93
|
+
name = 'KeyAuthorization.UnsupportedCallError';
|
|
94
|
+
}
|
|
95
|
+
/** A limit names a token that is not supported on the chain. */
|
|
96
|
+
export class UnsupportedTokenError extends ErrorResponse.define('unsupported_token') {
|
|
97
|
+
name = 'KeyAuthorization.UnsupportedTokenError';
|
|
98
|
+
}
|
|
99
|
+
/** The key names a passkey-owned Tempo Account, whose passkey signs only on a Tempo ID page. */
|
|
100
|
+
export class WebAuthnRequiredError extends ErrorResponse.define('webauthn_required') {
|
|
101
|
+
name = 'KeyAuthorization.WebAuthnRequiredError';
|
|
102
|
+
constructor(options) {
|
|
103
|
+
super({
|
|
104
|
+
error_description: options.description ??
|
|
105
|
+
`Passkey required: Tempo Account ${options.account} signs key authorizations only with its passkey, on a Tempo ID page. Authorize through a redirect, popup, or device grant, or name another account.`,
|
|
106
|
+
field: 'key_authorization.account',
|
|
107
|
+
meta: { account: options.account },
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** A `0x`-prefixed hex string. Its digits are checked, since quantities decode with `Hex.toBigInt`. */
|
|
112
|
+
const hex = z
|
|
113
|
+
.templateLiteral(['0x', z.string().regex(/^[0-9a-fA-F]*$/)])
|
|
114
|
+
.meta({ pattern: '^0x[0-9a-fA-F]*$' });
|
|
115
|
+
/** A 20-byte address. */
|
|
116
|
+
const address = z
|
|
117
|
+
.templateLiteral(['0x', z.string().regex(/^[0-9a-fA-F]{40}$/)])
|
|
118
|
+
.meta({ pattern: '^0x[0-9a-fA-F]{40}$' });
|
|
119
|
+
/**
|
|
120
|
+
* A hex quantity of at most 256 bits, the width of every on-chain quantity a key names. The bound
|
|
121
|
+
* keeps an oversized value from costing work before the request is authenticated.
|
|
122
|
+
*/
|
|
123
|
+
const quantity = z
|
|
124
|
+
.templateLiteral(['0x', z.string().regex(/^[0-9a-fA-F]{0,64}$/)])
|
|
125
|
+
.meta({ pattern: '^0x[0-9a-fA-F]{0,64}$' });
|
|
126
|
+
/** A 32-byte value as hex. */
|
|
127
|
+
const bytes32 = z
|
|
128
|
+
.templateLiteral(['0x', z.string().regex(/^[0-9a-fA-F]{64}$/)])
|
|
129
|
+
.meta({ pattern: '^0x[0-9a-fA-F]{64}$' });
|
|
130
|
+
/**
|
|
131
|
+
* A bigint, sent as a hex quantity. Zod drops examples on a codec's input, so the hex form carries
|
|
132
|
+
* the field's `examples`.
|
|
133
|
+
*/
|
|
134
|
+
function bigint(options) {
|
|
135
|
+
return z.codec(z.union([quantity.meta({ examples: options.examples }), z.bigint()]), z.bigint(), {
|
|
136
|
+
decode: (value) => typeof value === 'bigint'
|
|
137
|
+
? value
|
|
138
|
+
: value === '0x'
|
|
139
|
+
? 0n
|
|
140
|
+
: Hex.toBigInt(value),
|
|
141
|
+
encode: (value) => Hex.fromNumber(value),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* An app's key authorization request as sent: the shape of the Accounts SDK's `wallet_connect`
|
|
146
|
+
* `authorizeAccessKey` capability, with the user's Tempo Account it acts for.
|
|
147
|
+
*/
|
|
148
|
+
const sent = z.object({
|
|
149
|
+
/** The user's Tempo Account the key acts for. Defaults to the one they selected at sign-in, or their oldest. */
|
|
150
|
+
account: z.optional(address).meta({
|
|
151
|
+
description: 'The Tempo Account the key acts for. Defaults to the account selected at sign-in, or else the oldest account.',
|
|
152
|
+
examples: ['0x9a073914db0d149375ac2b7fbb72c68c0780fb5f'],
|
|
153
|
+
}),
|
|
154
|
+
/** The access key's address. `publicKey` may stand in for it. */
|
|
155
|
+
address: z.optional(address).meta({
|
|
156
|
+
description: "The access key's address. Required unless `publicKey` is present.",
|
|
157
|
+
examples: ['0x81c0f22bd173c115d18eeea0f6a38e935ecf52fb'],
|
|
158
|
+
}),
|
|
159
|
+
/** The chain the key acts on. Defaults to Tempo mainnet. */
|
|
160
|
+
chainId: z.optional(bigint({ examples: ['0x1079'] })).meta({
|
|
161
|
+
description: 'The chain ID the key acts on, as a hex quantity. Defaults to Tempo mainnet.',
|
|
162
|
+
}),
|
|
163
|
+
/** When the key expires, in Unix seconds. Defaults to a year from now. */
|
|
164
|
+
expiry: z.optional(z.number()).meta({
|
|
165
|
+
description: 'When the key expires, in Unix seconds. Defaults to one year after the request. A headless request allows at most one year.',
|
|
166
|
+
examples: [1893456000],
|
|
167
|
+
}),
|
|
168
|
+
/** The key's type. Defaults to `secp256k1`. */
|
|
169
|
+
keyType: z.optional(z.enum(['p256', 'secp256k1', 'webAuthn'])).meta({
|
|
170
|
+
description: 'The signature scheme of the access key. Defaults to `secp256k1`.',
|
|
171
|
+
examples: ['secp256k1'],
|
|
172
|
+
}),
|
|
173
|
+
/** How much of each token the key may spend. Defaults to the cap of each token it calls, or of OUSD. */
|
|
174
|
+
limits: z
|
|
175
|
+
.optional(z
|
|
176
|
+
.array(z.object({
|
|
177
|
+
limit: bigint({ examples: ['0x989680'] }).meta({
|
|
178
|
+
description: 'The most of the token the key may spend, in base units, as a hex quantity. Applies per period when `period` is set.',
|
|
179
|
+
}),
|
|
180
|
+
period: z.optional(z.number()).meta({
|
|
181
|
+
description: 'Seconds after which the limit resets. Omitted or 0 for a one-time limit.',
|
|
182
|
+
examples: [86400],
|
|
183
|
+
}),
|
|
184
|
+
token: address.meta({
|
|
185
|
+
description: 'The TIP-20 token the limit applies to.',
|
|
186
|
+
examples: ['0x20c0000000000000000000006a37DA5C996874BE'],
|
|
187
|
+
}),
|
|
188
|
+
}))
|
|
189
|
+
.readonly())
|
|
190
|
+
.meta({
|
|
191
|
+
description: 'The spending limit on each token. Defaults to the cap of each token the scopes call, or else of OUSD.',
|
|
192
|
+
}),
|
|
193
|
+
/** The access key's public key. */
|
|
194
|
+
publicKey: z.optional(hex).meta({
|
|
195
|
+
description: "The access key's uncompressed public key, as hex. Tempo ID derives `address` from it when `address` is absent.",
|
|
196
|
+
examples: [
|
|
197
|
+
'0x0438ef39ed22456a6956f380ebc18c50bd18c0402658bc52903817cc8a1e8b2f7ed1da68afc7f343c1debc44c04ac60e62e96bbb261d2226e7a7b96e64fd0f0765',
|
|
198
|
+
],
|
|
199
|
+
}),
|
|
200
|
+
/** The calls the key may make. Defaults to transfers of each token it limits. */
|
|
201
|
+
scopes: z
|
|
202
|
+
.optional(z
|
|
203
|
+
.array(z.object({
|
|
204
|
+
address: address.meta({
|
|
205
|
+
description: 'The TIP-20 token contract the key may call.',
|
|
206
|
+
examples: ['0x20c0000000000000000000006a37DA5C996874BE'],
|
|
207
|
+
}),
|
|
208
|
+
recipients: z.optional(z.array(address).readonly()).meta({
|
|
209
|
+
description: 'The only addresses the call may name as recipient or spender. Required for `approve`.',
|
|
210
|
+
examples: [['0xff5deded16eb46018387144ff8bf41f26afb41af']],
|
|
211
|
+
}),
|
|
212
|
+
selector: z.optional(z.union([hex, z.string().max(256)])).meta({
|
|
213
|
+
description: 'The function the key may call, as a 4-byte selector or a function signature: `transfer`, `transferWithMemo`, or `approve`. A scope without a selector is refused.',
|
|
214
|
+
examples: ['0xa9059cbb', 'transfer(address,uint256)'],
|
|
215
|
+
}),
|
|
216
|
+
}))
|
|
217
|
+
.readonly())
|
|
218
|
+
.meta({
|
|
219
|
+
description: 'The calls the key may make. Defaults to `transfer` and `transferWithMemo` on each token the key limits.',
|
|
220
|
+
}),
|
|
221
|
+
});
|
|
222
|
+
/** Zod schemas for key authorization requests, and for the API's responses about them. */
|
|
223
|
+
export var schema;
|
|
224
|
+
(function (schema) {
|
|
225
|
+
/** The Tempo Account a signed key acts for. */
|
|
226
|
+
schema.account = address.meta({
|
|
227
|
+
description: 'The Tempo Account the key acts for.',
|
|
228
|
+
examples: ['0x9a073914db0d149375ac2b7fbb72c68c0780fb5f'],
|
|
229
|
+
});
|
|
230
|
+
/** An app's key authorization request, with what it leaves out filled with the headless ceiling. */
|
|
231
|
+
schema.request = z.optional(sent.transform(defaults)).meta({
|
|
232
|
+
description: "A key authorization for the app's own key: the shape of the Accounts SDK's `wallet_connect` `authorizeAccessKey` capability. Omitted fields default to the headless ceiling.",
|
|
233
|
+
id: 'KeyAuthorizationRequest',
|
|
234
|
+
});
|
|
235
|
+
/** What a key grants, as `describe` returns it for the approval screens. */
|
|
236
|
+
schema.description = z
|
|
237
|
+
.object({
|
|
238
|
+
account: address.optional().meta({
|
|
239
|
+
description: 'The Tempo Account the request names. Absent when the request names none.',
|
|
240
|
+
examples: ['0x9a073914db0d149375ac2b7fbb72c68c0780fb5f'],
|
|
241
|
+
}),
|
|
242
|
+
expiry: z.number().meta({
|
|
243
|
+
description: 'Unix seconds.',
|
|
244
|
+
examples: [1893456000],
|
|
245
|
+
}),
|
|
246
|
+
limits: z
|
|
247
|
+
.array(z.object({
|
|
248
|
+
amount: z.string().meta({
|
|
249
|
+
description: 'In whole units.',
|
|
250
|
+
examples: ['1000'],
|
|
251
|
+
}),
|
|
252
|
+
currency: z.string().meta({
|
|
253
|
+
description: "The tokens' currency, such as `USD`. A yield-bearing token names its own.",
|
|
254
|
+
examples: ['USD'],
|
|
255
|
+
}),
|
|
256
|
+
period: z
|
|
257
|
+
.number()
|
|
258
|
+
.optional()
|
|
259
|
+
.meta({
|
|
260
|
+
description: 'Seconds after which the amount resets. Omitted for a one-time limit.',
|
|
261
|
+
examples: [86400],
|
|
262
|
+
}),
|
|
263
|
+
tokens: z
|
|
264
|
+
.array(z.object({
|
|
265
|
+
amount: z.string().meta({
|
|
266
|
+
description: "The token's own limit, in whole units.",
|
|
267
|
+
examples: ['1000'],
|
|
268
|
+
}),
|
|
269
|
+
symbol: z.string().meta({
|
|
270
|
+
description: "The token's symbol, or its address when the token has no symbol.",
|
|
271
|
+
examples: ['OUSD'],
|
|
272
|
+
}),
|
|
273
|
+
}))
|
|
274
|
+
.readonly()
|
|
275
|
+
.meta({ description: 'The tokens the amount spans.' }),
|
|
276
|
+
}))
|
|
277
|
+
.readonly()
|
|
278
|
+
.meta({
|
|
279
|
+
description: 'The spending limits, totaled for each currency and period.',
|
|
280
|
+
}),
|
|
281
|
+
})
|
|
282
|
+
.meta({
|
|
283
|
+
description: 'What a key authorization grants, for approval screens.',
|
|
284
|
+
id: 'KeyAuthorizationDescription',
|
|
285
|
+
});
|
|
286
|
+
/** A primitive signature envelope, in the node's RPC format. */
|
|
287
|
+
const primitive = z
|
|
288
|
+
.discriminatedUnion('type', [
|
|
289
|
+
z
|
|
290
|
+
.object({
|
|
291
|
+
r: hex.meta({
|
|
292
|
+
description: "The signature's 32-byte `r` value.",
|
|
293
|
+
examples: [
|
|
294
|
+
'0x12fe6a88b99377b94d6a628a86b9df544202c7b03827f44b16ee1a266ab98e17',
|
|
295
|
+
],
|
|
296
|
+
}),
|
|
297
|
+
s: hex.meta({
|
|
298
|
+
description: "The signature's 32-byte `s` value.",
|
|
299
|
+
examples: [
|
|
300
|
+
'0x4b6aa3723402498e07fb1f071673bd969d9f49a286af15ac60581d07ade24b77',
|
|
301
|
+
],
|
|
302
|
+
}),
|
|
303
|
+
type: z.literal('secp256k1').meta({
|
|
304
|
+
description: 'A secp256k1 ECDSA signature.',
|
|
305
|
+
}),
|
|
306
|
+
v: hex.optional().meta({
|
|
307
|
+
description: 'The legacy recovery value, which `yParity` replaces. Absent in most envelopes.',
|
|
308
|
+
examples: ['0x1c'],
|
|
309
|
+
}),
|
|
310
|
+
yParity: hex.meta({
|
|
311
|
+
description: 'The parity of the y-coordinate of the curve point, `0x0` or `0x1`.',
|
|
312
|
+
examples: ['0x1'],
|
|
313
|
+
}),
|
|
314
|
+
})
|
|
315
|
+
.meta({ description: 'A secp256k1 signature.' }),
|
|
316
|
+
z
|
|
317
|
+
.object({
|
|
318
|
+
preHash: z.boolean().meta({
|
|
319
|
+
description: 'Whether the signer hashed the digest with SHA-256 before signing it, as WebCrypto keys do.',
|
|
320
|
+
examples: [true],
|
|
321
|
+
}),
|
|
322
|
+
pubKeyX: hex.meta({
|
|
323
|
+
description: "The 32-byte x-coordinate of the signer's P256 public key.",
|
|
324
|
+
examples: [
|
|
325
|
+
'0xdae3e3e5faba0a2aca73d4d2a4b84ad46460f3f23af8a60b17b8a13537cfd440',
|
|
326
|
+
],
|
|
327
|
+
}),
|
|
328
|
+
pubKeyY: hex.meta({
|
|
329
|
+
description: "The 32-byte y-coordinate of the signer's P256 public key.",
|
|
330
|
+
examples: [
|
|
331
|
+
'0x816438c87ffd782cd0e37355eb83fbe1d4e5e905eaafa22fa27c32cc4abf7802',
|
|
332
|
+
],
|
|
333
|
+
}),
|
|
334
|
+
r: hex.meta({
|
|
335
|
+
description: "The signature's 32-byte `r` value.",
|
|
336
|
+
examples: [
|
|
337
|
+
'0x9da52cc71c005844434ce6996f7ea3b3262f84ec3a5d54f1d22d0bba9f2e5ea9',
|
|
338
|
+
],
|
|
339
|
+
}),
|
|
340
|
+
s: hex.meta({
|
|
341
|
+
description: "The signature's 32-byte `s` value.",
|
|
342
|
+
examples: [
|
|
343
|
+
'0x4b6aa3723402498e07fb1f071673bd969d9f49a286af15ac60581d07ade24b77',
|
|
344
|
+
],
|
|
345
|
+
}),
|
|
346
|
+
type: z.literal('p256').meta({
|
|
347
|
+
description: 'A P256 (secp256r1) signature.',
|
|
348
|
+
}),
|
|
349
|
+
})
|
|
350
|
+
.meta({ description: 'A P256 signature, with its public key.' }),
|
|
351
|
+
z
|
|
352
|
+
.object({
|
|
353
|
+
pubKeyX: hex.meta({
|
|
354
|
+
description: "The 32-byte x-coordinate of the passkey's P256 public key.",
|
|
355
|
+
examples: [
|
|
356
|
+
'0xdae3e3e5faba0a2aca73d4d2a4b84ad46460f3f23af8a60b17b8a13537cfd440',
|
|
357
|
+
],
|
|
358
|
+
}),
|
|
359
|
+
pubKeyY: hex.meta({
|
|
360
|
+
description: "The 32-byte y-coordinate of the passkey's P256 public key.",
|
|
361
|
+
examples: [
|
|
362
|
+
'0x816438c87ffd782cd0e37355eb83fbe1d4e5e905eaafa22fa27c32cc4abf7802',
|
|
363
|
+
],
|
|
364
|
+
}),
|
|
365
|
+
r: hex.meta({
|
|
366
|
+
description: "The signature's 32-byte `r` value.",
|
|
367
|
+
examples: [
|
|
368
|
+
'0x9da52cc71c005844434ce6996f7ea3b3262f84ec3a5d54f1d22d0bba9f2e5ea9',
|
|
369
|
+
],
|
|
370
|
+
}),
|
|
371
|
+
s: hex.meta({
|
|
372
|
+
description: "The signature's 32-byte `s` value.",
|
|
373
|
+
examples: [
|
|
374
|
+
'0x4b6aa3723402498e07fb1f071673bd969d9f49a286af15ac60581d07ade24b77',
|
|
375
|
+
],
|
|
376
|
+
}),
|
|
377
|
+
type: z.literal('webAuthn').meta({
|
|
378
|
+
description: 'A WebAuthn passkey signature.',
|
|
379
|
+
}),
|
|
380
|
+
webauthnData: hex.meta({
|
|
381
|
+
description: "The assertion's authenticator data followed by its `clientDataJSON`, as hex.",
|
|
382
|
+
examples: [
|
|
383
|
+
'0xa7cb28053c8ee4e5394fc67a0018dc1c622dad5ce3591b8ca13094ae86d11ba605000000007b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2271334a306257467a6157356e6247567a6157647559585231636d566b6157646c633352765a6d746c65574631644767222c226f726967696e223a2268747470733a2f2f617574682e74656d706f2e78797a222c2263726f73734f726967696e223a66616c73657d',
|
|
384
|
+
],
|
|
385
|
+
}),
|
|
386
|
+
})
|
|
387
|
+
.meta({ description: 'A WebAuthn signature, with its public key.' }),
|
|
388
|
+
])
|
|
389
|
+
.meta({
|
|
390
|
+
description: 'A signature by one key, as secp256k1, P256, or WebAuthn.',
|
|
391
|
+
});
|
|
392
|
+
/** A signed key authorization in the node's RPC format, as `sign` returns it. */
|
|
393
|
+
schema.rpc = z
|
|
394
|
+
.object({
|
|
395
|
+
account: address
|
|
396
|
+
.nullable()
|
|
397
|
+
.optional()
|
|
398
|
+
.meta({
|
|
399
|
+
description: 'The Tempo Account the key is bound to (TIP-1049). Absent or null when the key has no account binding.',
|
|
400
|
+
examples: ['0x9a073914db0d149375ac2b7fbb72c68c0780fb5f'],
|
|
401
|
+
}),
|
|
402
|
+
allowedCalls: z
|
|
403
|
+
.array(z.object({
|
|
404
|
+
selectorRules: z
|
|
405
|
+
.array(z.object({
|
|
406
|
+
recipients: z
|
|
407
|
+
.array(address)
|
|
408
|
+
.readonly()
|
|
409
|
+
.optional()
|
|
410
|
+
.meta({
|
|
411
|
+
description: 'The only addresses the call may name as recipient or spender. Absent when any address may receive.',
|
|
412
|
+
examples: [
|
|
413
|
+
['0xff5deded16eb46018387144ff8bf41f26afb41af'],
|
|
414
|
+
],
|
|
415
|
+
}),
|
|
416
|
+
selector: hex.meta({
|
|
417
|
+
description: 'The 4-byte selector of the function the key may call.',
|
|
418
|
+
examples: ['0xa9059cbb'],
|
|
419
|
+
}),
|
|
420
|
+
}))
|
|
421
|
+
.readonly()
|
|
422
|
+
.optional()
|
|
423
|
+
.meta({
|
|
424
|
+
description: 'The functions the key may call on the target. Absent when the key may call any function on it.',
|
|
425
|
+
}),
|
|
426
|
+
target: address.meta({
|
|
427
|
+
description: 'The contract the key may call.',
|
|
428
|
+
examples: ['0x20c0000000000000000000006a37DA5C996874BE'],
|
|
429
|
+
}),
|
|
430
|
+
}))
|
|
431
|
+
.readonly()
|
|
432
|
+
.optional()
|
|
433
|
+
.meta({
|
|
434
|
+
description: 'The calls the key may make. Absent when the key may make any call.',
|
|
435
|
+
}),
|
|
436
|
+
chainId: hex.meta({
|
|
437
|
+
description: 'The chain ID the key acts on, as a hex quantity.',
|
|
438
|
+
examples: ['0xa5bf'],
|
|
439
|
+
}),
|
|
440
|
+
expiry: hex
|
|
441
|
+
.nullable()
|
|
442
|
+
.optional()
|
|
443
|
+
.meta({
|
|
444
|
+
description: 'When the key expires, in Unix seconds, as a hex quantity. Absent or null when the key never expires.',
|
|
445
|
+
examples: ['0x6acdc1b4'],
|
|
446
|
+
}),
|
|
447
|
+
keyId: address.meta({
|
|
448
|
+
description: "The access key's address.",
|
|
449
|
+
examples: ['0x81c0f22bd173c115d18eeea0f6a38e935ecf52fb'],
|
|
450
|
+
}),
|
|
451
|
+
keyType: z.string().meta({
|
|
452
|
+
description: 'The signature scheme of the access key: `secp256k1`, `p256`, or `webAuthn`. The node names a configurable account key `multisig`.',
|
|
453
|
+
examples: ['secp256k1'],
|
|
454
|
+
}),
|
|
455
|
+
limits: z
|
|
456
|
+
.array(z.object({
|
|
457
|
+
limit: hex.meta({
|
|
458
|
+
description: 'The most of the token the key may spend, in base units, as a hex quantity. Applies per period when `period` is set.',
|
|
459
|
+
examples: ['0x989680'],
|
|
460
|
+
}),
|
|
461
|
+
period: hex.optional().meta({
|
|
462
|
+
description: 'Seconds after which the limit resets, as a hex quantity. Absent or `0x0` for a one-time limit.',
|
|
463
|
+
examples: ['0x15180'],
|
|
464
|
+
}),
|
|
465
|
+
token: address.meta({
|
|
466
|
+
description: 'The TIP-20 token the limit applies to.',
|
|
467
|
+
examples: ['0x20c0000000000000000000006a37DA5C996874BE'],
|
|
468
|
+
}),
|
|
469
|
+
}))
|
|
470
|
+
.readonly()
|
|
471
|
+
.optional()
|
|
472
|
+
.meta({
|
|
473
|
+
description: 'The spending limit on each token. Absent when spending is unlimited. An empty list allows no spending.',
|
|
474
|
+
}),
|
|
475
|
+
signature: z
|
|
476
|
+
.union([
|
|
477
|
+
hex.meta({
|
|
478
|
+
description: "A configurable account's RLP-encoded signature, which carries its owner approvals.",
|
|
479
|
+
examples: [
|
|
480
|
+
'0xf8a094ff5deded16eb46018387144ff8bf41f26afb41afc0f87cf87a80a012fe6a88b99377b94d6a628a86b9df544202c7b03827f44b16ee1a266ab98e17a04b6aa3723402498e07fb1f071673bd969d9f49a286af15ac60581d07ade24b77',
|
|
481
|
+
],
|
|
482
|
+
}),
|
|
483
|
+
primitive,
|
|
484
|
+
z
|
|
485
|
+
.object({
|
|
486
|
+
keyId: address.optional().meta({
|
|
487
|
+
description: 'The address of the access key that signed. Recovered from `signature` when absent.',
|
|
488
|
+
examples: ['0x624f27c462b885a83c698cac444a106a8c519e25'],
|
|
489
|
+
}),
|
|
490
|
+
signature: primitive.meta({
|
|
491
|
+
description: "The access key's own signature.",
|
|
492
|
+
}),
|
|
493
|
+
type: z.literal('keychain').meta({
|
|
494
|
+
description: 'A signature by an access key for an account.',
|
|
495
|
+
}),
|
|
496
|
+
userAddress: address.meta({
|
|
497
|
+
description: 'The Tempo Account the access key signs for.',
|
|
498
|
+
examples: ['0x9a073914db0d149375ac2b7fbb72c68c0780fb5f'],
|
|
499
|
+
}),
|
|
500
|
+
version: z
|
|
501
|
+
.enum(['v1', 'v2'])
|
|
502
|
+
.optional()
|
|
503
|
+
.meta({
|
|
504
|
+
description: 'The keychain signature version. `v2` binds the signature to `userAddress`. Defaults to `v1`.',
|
|
505
|
+
examples: ['v2'],
|
|
506
|
+
}),
|
|
507
|
+
})
|
|
508
|
+
.meta({
|
|
509
|
+
description: 'An access key signature that wraps a primitive signature.',
|
|
510
|
+
}),
|
|
511
|
+
])
|
|
512
|
+
.meta({
|
|
513
|
+
description: "The owner's signature envelope, in the node's format.",
|
|
514
|
+
}),
|
|
515
|
+
witness: bytes32.optional().meta({
|
|
516
|
+
description: 'The witness the signature binds, when the request sent one.',
|
|
517
|
+
examples: [
|
|
518
|
+
'0xf1e22f902be2546fe35d49388503ef7ea5c6c0e95a0f4b89d474e58793b64dec',
|
|
519
|
+
],
|
|
520
|
+
}),
|
|
521
|
+
})
|
|
522
|
+
.meta({
|
|
523
|
+
description: "A signed key authorization (TIP-1011), in the node's RPC format.",
|
|
524
|
+
id: 'KeyAuthorization',
|
|
525
|
+
});
|
|
526
|
+
})(schema || (schema = {}));
|
|
527
|
+
/** The longest a headless key lasts, in seconds, and how long a key lasts when its request names no expiry. */
|
|
528
|
+
export const lifetime = 365 * 24 * 60 * 60;
|
|
529
|
+
/** OUSD's address, the same on every Tempo chain. A key that names no token defaults to it. */
|
|
530
|
+
const ousd = openUsd(tempo.id).address;
|
|
531
|
+
/** Tempo chains, whose token addresses Viem's token list holds. */
|
|
532
|
+
export const chains = [tempo, tempoTestnet, tempoDevnet, tempoLocalnet];
|
|
533
|
+
/** The ID of the chain that a key acts on when its request names none: Tempo mainnet. */
|
|
534
|
+
export const defaultChainId = tempo.id;
|
|
535
|
+
/** About $1,000 in each currency, in whole units. Unlisted currencies are yield-bearing dollars. */
|
|
536
|
+
// ponytail: the rates are fixed. If caps must track markets closely, price them live.
|
|
537
|
+
const caps = {
|
|
538
|
+
BRL: '5000',
|
|
539
|
+
BTC: '0.01',
|
|
540
|
+
CHF: '800',
|
|
541
|
+
EUR: '850',
|
|
542
|
+
GBP: '750',
|
|
543
|
+
USD: '1000',
|
|
544
|
+
};
|
|
545
|
+
/** Every Tempo token in Viem's token list, by chain ID and lowercase address, with its cap in base units. */
|
|
546
|
+
const listed = new Map(tokens.tempo.flatMap((token) => chains.flatMap((chain) => {
|
|
547
|
+
const addresses = token.addresses;
|
|
548
|
+
// A local Tempo node predeploys the testnet's tokens, at the same addresses. OUSD has its
|
|
549
|
+
// mainnet address on every Tempo chain, which Viem's list names only for mainnet.
|
|
550
|
+
// ponytail: drop the OUSD fallback once Viem lists OUSD on testnet.
|
|
551
|
+
const address = addresses[chain.id] ??
|
|
552
|
+
(chain.id === tempoLocalnet.id
|
|
553
|
+
? addresses[tempoTestnet.id]
|
|
554
|
+
: undefined) ??
|
|
555
|
+
(token.symbol === 'OUSD' ? addresses[tempo.id] : undefined);
|
|
556
|
+
if (!address)
|
|
557
|
+
return [];
|
|
558
|
+
const cap = caps[token.currency ?? ''] ?? caps.USD;
|
|
559
|
+
return [
|
|
560
|
+
[
|
|
561
|
+
`${chain.id}:${address.toLowerCase()}`,
|
|
562
|
+
{
|
|
563
|
+
address: Address.checksum(address),
|
|
564
|
+
cap: Value.from(cap, token.decimals),
|
|
565
|
+
currency: token.currency,
|
|
566
|
+
decimals: token.decimals,
|
|
567
|
+
symbol: token.symbol ?? address,
|
|
568
|
+
},
|
|
569
|
+
],
|
|
570
|
+
];
|
|
571
|
+
})));
|
|
572
|
+
/**
|
|
573
|
+
* TIP-20 calls whose spending the key's limits bound. `approve` needs a spender allowlist, since an
|
|
574
|
+
* approved spender moves tokens without the key ([TIP-1011](https://tips.sh/1011)).
|
|
575
|
+
*/
|
|
576
|
+
const calls = {
|
|
577
|
+
approve: AbiFunction.getSelector('approve(address,uint256)'),
|
|
578
|
+
transfer: AbiFunction.getSelector('transfer(address,uint256)'),
|
|
579
|
+
transferWithMemo: AbiFunction.getSelector('transferWithMemo(address,uint256,bytes32)'),
|
|
580
|
+
};
|
|
581
|
+
/**
|
|
582
|
+
* Returns `key` with the witness of `challenge`: its EIP-191 hash, as `hashMessage` computes it, so
|
|
583
|
+
* a verifier checks the witness against the message it issued. Returns `key` unchanged without one.
|
|
584
|
+
*/
|
|
585
|
+
export function bind(key, options) {
|
|
586
|
+
if (options.challenge === undefined)
|
|
587
|
+
return key;
|
|
588
|
+
return { ...key, witness: hashMessage(options.challenge) };
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Why `key` breaks the rules every flow applies, with the field at fault and the values compared,
|
|
592
|
+
* or `undefined` when the owner may sign it. Fields are request paths under `key_authorization`,
|
|
593
|
+
* where every request carries the key.
|
|
594
|
+
*/
|
|
595
|
+
export function check(key) {
|
|
596
|
+
const now = Math.floor(Date.now() / 1000);
|
|
597
|
+
// Nodes reject chain ID zero, so a key names its chain.
|
|
598
|
+
if (!key.chainId)
|
|
599
|
+
return new InvalidChainError({
|
|
600
|
+
error_description: 'Invalid `chainId`: 0. Use a Tempo chain ID, such as 4217.',
|
|
601
|
+
field: 'key_authorization.chainId',
|
|
602
|
+
meta: { chain_id: 0 },
|
|
603
|
+
});
|
|
604
|
+
const chainId = Number(key.chainId);
|
|
605
|
+
if (!key.address && !key.publicKey)
|
|
606
|
+
return new MissingKeyError({
|
|
607
|
+
error_description: 'Missing `address` or `publicKey`. Provide the access key.',
|
|
608
|
+
field: 'key_authorization.address',
|
|
609
|
+
});
|
|
610
|
+
// The chain rejects the zero address, which no key holds, also beside a public key.
|
|
611
|
+
if (key.address === zeroAddress)
|
|
612
|
+
return new MissingKeyError({
|
|
613
|
+
error_description: 'Invalid `address`: the zero address holds no key. Provide the address of the access key.',
|
|
614
|
+
field: 'key_authorization.address',
|
|
615
|
+
});
|
|
616
|
+
if (key.publicKey && !parse(key.publicKey))
|
|
617
|
+
return new InvalidPublicKeyError({
|
|
618
|
+
error_description: 'Invalid `publicKey`. Provide an uncompressed public key, or `address`.',
|
|
619
|
+
field: 'key_authorization.publicKey',
|
|
620
|
+
});
|
|
621
|
+
if (!Number.isSafeInteger(key.expiry))
|
|
622
|
+
return new InvalidExpiryError({
|
|
623
|
+
error_description: `Invalid \`expiry\`: ${key.expiry} is not a whole number of seconds. Use a future Unix time in seconds.`,
|
|
624
|
+
field: 'key_authorization.expiry',
|
|
625
|
+
meta: { expiry: key.expiry },
|
|
626
|
+
});
|
|
627
|
+
// Zero means the key never expires.
|
|
628
|
+
if (key.expiry === 0)
|
|
629
|
+
return new InvalidExpiryError({
|
|
630
|
+
error_description: 'Invalid `expiry`: 0 never expires. Use a future Unix time.',
|
|
631
|
+
field: 'key_authorization.expiry',
|
|
632
|
+
meta: { expiry: 0 },
|
|
633
|
+
});
|
|
634
|
+
if (key.expiry <= now)
|
|
635
|
+
return new ExpiryPassedError({
|
|
636
|
+
error_description: `Invalid \`expiry\`: ${date(key.expiry)} has passed. Use a future Unix time.`,
|
|
637
|
+
field: 'key_authorization.expiry',
|
|
638
|
+
meta: { expiry: key.expiry, now },
|
|
639
|
+
});
|
|
640
|
+
if (!key.limits.length)
|
|
641
|
+
return new EmptyLimitsError({
|
|
642
|
+
error_description: 'Empty `limits`. Name at least one token, or omit `limits`.',
|
|
643
|
+
field: 'key_authorization.limits',
|
|
644
|
+
});
|
|
645
|
+
if (!key.scopes.length)
|
|
646
|
+
return new EmptyScopesError({
|
|
647
|
+
error_description: 'Empty `scopes`. Name at least one call, or omit `scopes`.',
|
|
648
|
+
field: 'key_authorization.scopes',
|
|
649
|
+
});
|
|
650
|
+
// A scope's token is checked first, since `defaults` adds a limit for it that the request did not send.
|
|
651
|
+
for (const [index, scope] of key.scopes.entries())
|
|
652
|
+
if (!token(key, scope.address))
|
|
653
|
+
return new UnsupportedTokenError({
|
|
654
|
+
error_description: `Unsupported token on chain ${chainId}: ${scope.address}. Use a supported token, such as OUSD.`,
|
|
655
|
+
field: `key_authorization.scopes.${index}.address`,
|
|
656
|
+
meta: { chain_id: chainId, token: scope.address },
|
|
657
|
+
});
|
|
658
|
+
const seen = new Set();
|
|
659
|
+
for (const [index, limit] of key.limits.entries()) {
|
|
660
|
+
// TIP-1011 rejects a key that limits one token twice.
|
|
661
|
+
if (seen.has(limit.token.toLowerCase()))
|
|
662
|
+
return new DuplicateLimitError({
|
|
663
|
+
error_description: `Duplicate limit for ${limit.token}. Limit each token once.`,
|
|
664
|
+
field: `key_authorization.limits.${index}.token`,
|
|
665
|
+
meta: { token: limit.token },
|
|
666
|
+
});
|
|
667
|
+
seen.add(limit.token.toLowerCase());
|
|
668
|
+
const listing = token(key, limit.token);
|
|
669
|
+
if (!listing)
|
|
670
|
+
return new UnsupportedTokenError({
|
|
671
|
+
error_description: `Unsupported token on chain ${chainId}: ${limit.token}. Use a supported token, such as OUSD.`,
|
|
672
|
+
field: `key_authorization.limits.${index}.token`,
|
|
673
|
+
meta: { chain_id: chainId, token: limit.token },
|
|
674
|
+
});
|
|
675
|
+
if (limit.period !== undefined &&
|
|
676
|
+
(!Number.isSafeInteger(limit.period) || limit.period < 0))
|
|
677
|
+
return new InvalidPeriodError({
|
|
678
|
+
error_description: `Invalid \`period\` on the ${listing.symbol} limit: ${limit.period}. Use a whole number of seconds, or 0 for a one-time limit.`,
|
|
679
|
+
field: `key_authorization.limits.${index}.period`,
|
|
680
|
+
meta: {
|
|
681
|
+
period: limit.period,
|
|
682
|
+
symbol: listing.symbol,
|
|
683
|
+
token: listing.address,
|
|
684
|
+
},
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
const rules = new Set();
|
|
688
|
+
for (const [index, scope] of key.scopes.entries()) {
|
|
689
|
+
// Every call targets a token the key limits, so no call moves an unlimited token.
|
|
690
|
+
const listing = key.limits.some((limit) => Address.isEqual(limit.token, scope.address))
|
|
691
|
+
? token(key, scope.address)
|
|
692
|
+
: undefined;
|
|
693
|
+
if (!listing)
|
|
694
|
+
return new ScopeWithoutLimitError({
|
|
695
|
+
error_description: `Scope on ${scope.address} has no limit. Add a limit for it, or remove the scope.`,
|
|
696
|
+
field: `key_authorization.scopes.${index}.address`,
|
|
697
|
+
meta: { token: scope.address },
|
|
698
|
+
});
|
|
699
|
+
const selector = scope.selector ? normalize(scope.selector) : undefined;
|
|
700
|
+
const named = (() => {
|
|
701
|
+
if (selector)
|
|
702
|
+
return selector;
|
|
703
|
+
if (scope.selector)
|
|
704
|
+
return 'an unknown function';
|
|
705
|
+
return 'any function';
|
|
706
|
+
})();
|
|
707
|
+
if (selector === calls.approve && !scope.recipients?.length)
|
|
708
|
+
return new MissingRecipientsError({
|
|
709
|
+
error_description: `Missing \`recipients\` for \`approve\` on ${listing.symbol}. Name the allowed spenders.`,
|
|
710
|
+
field: `key_authorization.scopes.${index}.recipients`,
|
|
711
|
+
meta: { symbol: listing.symbol, token: listing.address },
|
|
712
|
+
});
|
|
713
|
+
if (selector !== calls.approve &&
|
|
714
|
+
selector !== calls.transfer &&
|
|
715
|
+
selector !== calls.transferWithMemo)
|
|
716
|
+
return new UnsupportedCallError({
|
|
717
|
+
// Only the normalized selector is echoed, so a request cannot place its own text on a page.
|
|
718
|
+
error_description: `Unsupported call on ${listing.symbol}: ${named}. Use \`transfer\`, \`transferWithMemo\`, or \`approve\`.`,
|
|
719
|
+
field: `key_authorization.scopes.${index}.selector`,
|
|
720
|
+
meta: {
|
|
721
|
+
...(selector ? { selector } : {}),
|
|
722
|
+
symbol: listing.symbol,
|
|
723
|
+
token: listing.address,
|
|
724
|
+
},
|
|
725
|
+
});
|
|
726
|
+
// TIP-1011 rejects a key that names one call on a token twice.
|
|
727
|
+
const rule = `${listing.address.toLowerCase()}:${selector}`;
|
|
728
|
+
if (rules.has(rule))
|
|
729
|
+
return new DuplicateScopeError({
|
|
730
|
+
error_description: `Duplicate scope for ${selector} on ${listing.symbol}. Name each call on a token once.`,
|
|
731
|
+
field: `key_authorization.scopes.${index}.selector`,
|
|
732
|
+
meta: { selector, symbol: listing.symbol, token: listing.address },
|
|
733
|
+
});
|
|
734
|
+
rules.add(rule);
|
|
735
|
+
// TIP-1011 rejects recipients that hold the zero address or repeat an address.
|
|
736
|
+
const recipients = (scope.recipients ?? []).map((entry) => entry.toLowerCase());
|
|
737
|
+
// One pass with a set keeps the check linear in the number of recipients.
|
|
738
|
+
const unique = new Set();
|
|
739
|
+
const position = recipients.findIndex((entry) => {
|
|
740
|
+
if (entry === zeroAddress || unique.has(entry))
|
|
741
|
+
return true;
|
|
742
|
+
unique.add(entry);
|
|
743
|
+
return false;
|
|
744
|
+
});
|
|
745
|
+
const recipient = scope.recipients?.[position];
|
|
746
|
+
if (recipient)
|
|
747
|
+
return new InvalidRecipientsError({
|
|
748
|
+
error_description: `Invalid recipient ${recipient} for ${selector} on ${listing.symbol}. Name each recipient once, and never the zero address.`,
|
|
749
|
+
field: `key_authorization.scopes.${index}.recipients.${position}`,
|
|
750
|
+
meta: { recipient, symbol: listing.symbol, token: listing.address },
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
return undefined;
|
|
754
|
+
}
|
|
755
|
+
(function (check) {
|
|
756
|
+
/** The refusals `check` returns. Its return type admits no other. */
|
|
757
|
+
check.errors = [
|
|
758
|
+
DuplicateLimitError,
|
|
759
|
+
DuplicateScopeError,
|
|
760
|
+
EmptyLimitsError,
|
|
761
|
+
EmptyScopesError,
|
|
762
|
+
ExpiryPassedError,
|
|
763
|
+
InvalidChainError,
|
|
764
|
+
InvalidExpiryError,
|
|
765
|
+
InvalidPeriodError,
|
|
766
|
+
InvalidPublicKeyError,
|
|
767
|
+
InvalidRecipientsError,
|
|
768
|
+
MissingKeyError,
|
|
769
|
+
MissingRecipientsError,
|
|
770
|
+
ScopeWithoutLimitError,
|
|
771
|
+
UnsupportedCallError,
|
|
772
|
+
UnsupportedTokenError,
|
|
773
|
+
];
|
|
774
|
+
})(check || (check = {}));
|
|
775
|
+
/**
|
|
776
|
+
* Why the request for `key` is refused for the app `app`. The request carries a challenge, which
|
|
777
|
+
* became the key's witness, and the app does not hold the `tempo-id:sign` scope. Returns `undefined`
|
|
778
|
+
* when the key has no witness or the app holds the scope. A browser request names a redirect URI on
|
|
779
|
+
* its own origin, which the app registers, so the app's scope covers its pages.
|
|
780
|
+
*/
|
|
781
|
+
export function checkChallenge(options) {
|
|
782
|
+
const { app, clientId, key } = options;
|
|
783
|
+
if (!key?.witness)
|
|
784
|
+
return undefined;
|
|
785
|
+
if (!app?.sign)
|
|
786
|
+
return new ChallengeNotPermittedError({ clientId });
|
|
787
|
+
return undefined;
|
|
788
|
+
}
|
|
789
|
+
(function (checkChallenge) {
|
|
790
|
+
/** The refusals `checkChallenge` returns. */
|
|
791
|
+
checkChallenge.errors = [ChallengeNotPermittedError];
|
|
792
|
+
})(checkChallenge || (checkChallenge = {}));
|
|
793
|
+
/**
|
|
794
|
+
* Why `key` is refused in a flow that shows the user nothing: the rules `check` applies, then the
|
|
795
|
+
* headless ceiling. Returns `undefined` when the owner may sign it.
|
|
796
|
+
*/
|
|
797
|
+
export function checkHeadless(key) {
|
|
798
|
+
const error = check(key);
|
|
799
|
+
if (error)
|
|
800
|
+
return error;
|
|
801
|
+
const now = Math.floor(Date.now() / 1000);
|
|
802
|
+
const chainId = Number(key.chainId);
|
|
803
|
+
if (key.expiry > now + lifetime)
|
|
804
|
+
return new ExpiryExceedsMaximumError({
|
|
805
|
+
error_description: `Invalid \`expiry\`: ${date(key.expiry)} exceeds the one-year maximum. Use an earlier expiry, or authorize through a redirect or device grant.`,
|
|
806
|
+
field: 'key_authorization.expiry',
|
|
807
|
+
meta: { expiry: key.expiry, maximum: now + lifetime },
|
|
808
|
+
});
|
|
809
|
+
for (const [index, limit] of key.limits.entries()) {
|
|
810
|
+
const listing = token(key, limit.token);
|
|
811
|
+
// A periodic limit resets each period, so the ceiling bounds what it allows before the key expires.
|
|
812
|
+
const periods = limit.period
|
|
813
|
+
? BigInt(Math.ceil((key.expiry - now) / limit.period))
|
|
814
|
+
: 1n;
|
|
815
|
+
const total = limit.limit * periods;
|
|
816
|
+
if (total > listing.cap)
|
|
817
|
+
return new LimitExceedsMaximumError({
|
|
818
|
+
error_description: `Invalid ${listing.symbol} limit: ${Value.format(total, listing.decimals)}${periods > 1n ? ` over ${periods} periods before the key expires` : ''} exceeds the ${Value.format(listing.cap, listing.decimals)} maximum. ${periods > 1n ? 'Lower the limit or shorten the expiry' : 'Lower the limit'}, or authorize through a redirect or device grant.`,
|
|
819
|
+
field: `key_authorization.limits.${index}.limit`,
|
|
820
|
+
meta: {
|
|
821
|
+
chain_id: chainId,
|
|
822
|
+
// The compared total: the limit, times its periods before the key expires.
|
|
823
|
+
limit: total.toString(),
|
|
824
|
+
maximum: listing.cap.toString(),
|
|
825
|
+
periods: Number(periods),
|
|
826
|
+
symbol: listing.symbol,
|
|
827
|
+
token: listing.address,
|
|
828
|
+
},
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
return undefined;
|
|
832
|
+
}
|
|
833
|
+
(function (checkHeadless) {
|
|
834
|
+
/** The refusals `checkHeadless` returns: `check`'s, then the headless ceiling's. */
|
|
835
|
+
checkHeadless.errors = [
|
|
836
|
+
...check.errors,
|
|
837
|
+
ExpiryExceedsMaximumError,
|
|
838
|
+
LimitExceedsMaximumError,
|
|
839
|
+
];
|
|
840
|
+
})(checkHeadless || (checkHeadless = {}));
|
|
841
|
+
/**
|
|
842
|
+
* What a `key` that passes `check` grants, as the approval screens show it: its limits totaled per
|
|
843
|
+
* currency and period, and its expiry.
|
|
844
|
+
*/
|
|
845
|
+
export function describe(key) {
|
|
846
|
+
// The screens state spending per currency, so limits on tokens of one currency and period add up.
|
|
847
|
+
const totals = new Map();
|
|
848
|
+
for (const limit of key.limits) {
|
|
849
|
+
const listing = token(key, limit.token);
|
|
850
|
+
const period = limit.period ?? 0;
|
|
851
|
+
const group = `${listing.currency}\0${period}`;
|
|
852
|
+
const total = totals.get(group);
|
|
853
|
+
if (!total) {
|
|
854
|
+
totals.set(group, {
|
|
855
|
+
amount: limit.limit,
|
|
856
|
+
currency: listing.currency,
|
|
857
|
+
decimals: listing.decimals,
|
|
858
|
+
period,
|
|
859
|
+
tokens: [
|
|
860
|
+
{
|
|
861
|
+
amount: Value.format(limit.limit, listing.decimals),
|
|
862
|
+
symbol: listing.symbol,
|
|
863
|
+
},
|
|
864
|
+
],
|
|
865
|
+
});
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
total.tokens.push({
|
|
869
|
+
amount: Value.format(limit.limit, listing.decimals),
|
|
870
|
+
symbol: listing.symbol,
|
|
871
|
+
});
|
|
872
|
+
const decimals = Math.max(total.decimals, listing.decimals);
|
|
873
|
+
total.amount =
|
|
874
|
+
total.amount * 10n ** BigInt(decimals - total.decimals) +
|
|
875
|
+
limit.limit * 10n ** BigInt(decimals - listing.decimals);
|
|
876
|
+
total.decimals = decimals;
|
|
877
|
+
}
|
|
878
|
+
return {
|
|
879
|
+
account: key.account,
|
|
880
|
+
expiry: key.expiry,
|
|
881
|
+
limits: [...totals.values()].map((total) => ({
|
|
882
|
+
amount: Value.format(total.amount, total.decimals),
|
|
883
|
+
currency: total.currency,
|
|
884
|
+
...(total.period ? { period: total.period } : {}),
|
|
885
|
+
tokens: total.tokens,
|
|
886
|
+
})),
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Returns the digest that an account's owner signs for `key`, which a passkey owner signs as its
|
|
891
|
+
* WebAuthn challenge. An owner's digest binds no account, so it is known before the passkey is.
|
|
892
|
+
* `witness` replaces the key's own, as a one-tap sign-in binds it.
|
|
893
|
+
*/
|
|
894
|
+
export function digest(options) {
|
|
895
|
+
const { key: accessKey, ...rest } = parameters(options.key);
|
|
896
|
+
return KeyAuthorization.getSignPayload({
|
|
897
|
+
...rest,
|
|
898
|
+
address: accessKey.address,
|
|
899
|
+
type: accessKey.type,
|
|
900
|
+
...(options.witness ? { witness: options.witness } : {}),
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
/** Returns the access key's address, which `publicKey` stands in for when the request names none. */
|
|
904
|
+
export function keyId(key) {
|
|
905
|
+
return parameters(key).key.address;
|
|
906
|
+
}
|
|
907
|
+
/** Returns the tokens of Viem's token list on the chain with `chainId`, as keys limit them. */
|
|
908
|
+
export function listings(options) {
|
|
909
|
+
const prefix = `${options.chainId}:`;
|
|
910
|
+
return [...listed].flatMap((entry) => entry[0].startsWith(prefix) ? [entry[1]] : []);
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Signs `key` with `owner`, the account's owner key, and returns the signed authorization in the
|
|
914
|
+
* node's RPC format. A Privy owner signs through Privy with the user's token.
|
|
915
|
+
*/
|
|
916
|
+
export async function sign(owner, options) {
|
|
917
|
+
return KeyAuthorization.toRpc(await Account.signKeyAuthorization(owner, parameters(options.key)));
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Signs `key` with `assertion`, a passkey's assertion over the key's {@link digest} that
|
|
921
|
+
* `Passkey.verify` accepted, and returns the signed authorization in the node's RPC format. The
|
|
922
|
+
* assertion becomes the authorization's WebAuthn signature envelope.
|
|
923
|
+
*/
|
|
924
|
+
export async function signWithAssertion(assertion, options) {
|
|
925
|
+
const { metadata, signature } = Authentication.deserializeResponse(assertion);
|
|
926
|
+
const challenge = digest({ key: options.key });
|
|
927
|
+
const publicKey = PublicKey.fromHex(options.publicKey);
|
|
928
|
+
// The passkey already signed the digest, so this owner returns the assertion as its envelope.
|
|
929
|
+
const owner = Account.from({
|
|
930
|
+
keyType: 'webAuthn',
|
|
931
|
+
publicKey,
|
|
932
|
+
sign(request) {
|
|
933
|
+
if (request.hash !== challenge)
|
|
934
|
+
return Promise.reject(new Error('The assertion signs another key authorization.'));
|
|
935
|
+
return Promise.resolve(SignatureEnvelope.serialize({
|
|
936
|
+
metadata: {
|
|
937
|
+
authenticatorData: metadata.authenticatorData,
|
|
938
|
+
clientDataJSON: metadata.clientDataJSON,
|
|
939
|
+
},
|
|
940
|
+
publicKey,
|
|
941
|
+
signature,
|
|
942
|
+
type: 'webAuthn',
|
|
943
|
+
}));
|
|
944
|
+
},
|
|
945
|
+
});
|
|
946
|
+
return await sign(owner, { key: options.key });
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Fills what a request leaves out with the headless ceiling:
|
|
950
|
+
*
|
|
951
|
+
* - Tempo mainnet.
|
|
952
|
+
* - A year.
|
|
953
|
+
* - The cap of each token it calls, or of OUSD.
|
|
954
|
+
* - Transfers of each token it limits.
|
|
955
|
+
*/
|
|
956
|
+
function defaults(key) {
|
|
957
|
+
const chainId = key.chainId ?? BigInt(defaultChainId);
|
|
958
|
+
// Empty scopes keep the default limit, so `check` refuses the scopes that the request sent.
|
|
959
|
+
const addresses = key.scopes?.length
|
|
960
|
+
? [...new Set(key.scopes.map((scope) => scope.address.toLowerCase()))]
|
|
961
|
+
: [ousd.toLowerCase()];
|
|
962
|
+
// A scope on an unlisted token keeps a zero limit, which `check` refuses at the scope.
|
|
963
|
+
const limits = key.limits ??
|
|
964
|
+
addresses.map((address) => {
|
|
965
|
+
const listing = listed.get(`${chainId}:${address}`);
|
|
966
|
+
return listing
|
|
967
|
+
? { limit: listing.cap, token: listing.address }
|
|
968
|
+
: { limit: 0n, token: Address.checksum(address) };
|
|
969
|
+
});
|
|
970
|
+
const scopes = key.scopes ??
|
|
971
|
+
limits.flatMap((limit) => [calls.transfer, calls.transferWithMemo].map((selector) => ({
|
|
972
|
+
address: limit.token,
|
|
973
|
+
selector,
|
|
974
|
+
})));
|
|
975
|
+
return {
|
|
976
|
+
...key,
|
|
977
|
+
chainId,
|
|
978
|
+
expiry: key.expiry ?? Math.floor(Date.now() / 1000) + lifetime,
|
|
979
|
+
limits,
|
|
980
|
+
scopes,
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
/** The listed token at `address` on the key's chain, if any. */
|
|
984
|
+
function token(key, address) {
|
|
985
|
+
return listed.get(`${Number(key.chainId)}:${address.toLowerCase()}`);
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* A selector as lowercase hex, from hex or a function signature, or `undefined` when the
|
|
989
|
+
* signature does not parse.
|
|
990
|
+
*/
|
|
991
|
+
function normalize(selector) {
|
|
992
|
+
if (/^0x[0-9a-fA-F]{8}$/.test(selector))
|
|
993
|
+
return selector.toLowerCase();
|
|
994
|
+
// The parser throws on a malformed signature, which the caller refuses as an unsupported call.
|
|
995
|
+
try {
|
|
996
|
+
return AbiFunction.getSelector(selector);
|
|
997
|
+
}
|
|
998
|
+
catch {
|
|
999
|
+
return undefined;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
/** The address of a public key, or `undefined` when it is not a valid point. */
|
|
1003
|
+
/** The fields of `key` that its owner signs, as Viem's `Account.signKeyAuthorization` takes them. */
|
|
1004
|
+
function parameters(key) {
|
|
1005
|
+
return {
|
|
1006
|
+
chainId: key.chainId,
|
|
1007
|
+
expiry: key.expiry,
|
|
1008
|
+
key: {
|
|
1009
|
+
address: key.address ?? parse(key.publicKey),
|
|
1010
|
+
// The Accounts SDK's default for a key the app holds.
|
|
1011
|
+
type: key.keyType ?? 'secp256k1',
|
|
1012
|
+
},
|
|
1013
|
+
limits: key.limits,
|
|
1014
|
+
scopes: key.scopes,
|
|
1015
|
+
...(key.witness ? { witness: key.witness } : {}),
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
/** A Unix time as a UTC date and time, for messages. */
|
|
1019
|
+
function date(seconds) {
|
|
1020
|
+
return new Date(seconds * 1000).toUTCString();
|
|
1021
|
+
}
|
|
1022
|
+
function parse(publicKey) {
|
|
1023
|
+
try {
|
|
1024
|
+
return Address.fromPublicKey(PublicKey.from(publicKey));
|
|
1025
|
+
}
|
|
1026
|
+
catch {
|
|
1027
|
+
return undefined;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
//# sourceMappingURL=KeyAuthorization.js.map
|