@asseteragmbh/wallet-connector 0.2.0 → 0.2.1
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 +82 -6
- package/dist/{chunk-ILCYZXH2.js → chunk-6OZIE56G.js} +5 -4
- package/dist/chunk-6OZIE56G.js.map +1 -0
- package/dist/{chunk-SU2ZKBZD.js → chunk-H7PEM735.js} +34 -4
- package/dist/chunk-H7PEM735.js.map +1 -0
- package/dist/{chunk-PD2FAZ7O.js → chunk-YJHLKN7O.js} +21 -5
- package/dist/chunk-YJHLKN7O.js.map +1 -0
- package/dist/index.cjs +154 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +72 -4
- package/dist/index.d.ts +72 -4
- package/dist/index.js +102 -16
- package/dist/index.js.map +1 -1
- package/dist/protocol.cjs +36 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +76 -7
- package/dist/protocol.d.ts +76 -7
- package/dist/protocol.js +1 -1
- package/dist/{provider-BEIsX3q_.d.ts → provider-Cn9rPKZh.d.cts} +20 -3
- package/dist/{provider-BEIsX3q_.d.cts → provider-OStA8Fqx.d.ts} +20 -3
- package/dist/rainbowkit.cjs +41 -5
- package/dist/rainbowkit.cjs.map +1 -1
- package/dist/rainbowkit.d.cts +4 -1
- package/dist/rainbowkit.d.ts +4 -1
- package/dist/rainbowkit.js +7 -4
- package/dist/rainbowkit.js.map +1 -1
- package/dist/wagmi.cjs +37 -4
- package/dist/wagmi.cjs.map +1 -1
- package/dist/wagmi.d.cts +5 -2
- package/dist/wagmi.d.ts +5 -2
- package/dist/wagmi.js +3 -3
- package/package.json +3 -3
- package/dist/chunk-ILCYZXH2.js.map +0 -1
- package/dist/chunk-PD2FAZ7O.js.map +0 -1
- package/dist/chunk-SU2ZKBZD.js.map +0 -1
package/dist/protocol.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":"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","file":"protocol.cjs","sourcesContent":["/**\n * The pop-up protocol between a partner page (the opener) and the Assetera Wallet (the pop-up) — ADR-0054 D3/D4.\n *\n * This file is the CONTRACT. The connector in this package speaks the opener side; AsseteraWalletFront's\n * `/connect` page speaks the pop-up side and imports these types from `@asseteragmbh/wallet-connector/protocol`.\n * Change it only in a backwards-compatible way, or bump `PROTOCOL_VERSION` and support both on the wallet side:\n * partner sites upgrade on their own schedule.\n *\n * ## The handshake\n *\n * 1. The partner opens `${walletUrl}${CONNECT_PATH}?origin=<partner origin>&v=<version>` from a user click.\n * 2. The pop-up checks the claimed origin against its allowlist (D4). If listed, it posts `ready` to\n * `window.opener` with `targetOrigin` = that origin. The browser delivers it ONLY if the opener really is\n * that origin, so a page cannot claim someone else's origin and still hear the answer.\n * 3. The opener waits for `ready` from the wallet origin, then sends `request`s with `targetOrigin` = the wallet\n * origin. The pop-up accepts a message only when `event.origin` is the allowed origin from step 2 AND\n * `event.source === window.opener`, and answers with `targetOrigin` = that origin. Nothing else is accepted.\n *\n * ## Lifetime\n *\n * The pop-up stays open while the partner uses the wallet (ADR-0054, \"the wallet tab must stay open\"). When it is\n * closed, the opener sees `disconnect` (or notices `popup.closed`) and must reconnect from a user click.\n *\n * ## Onboarding\n *\n * Onboarding is a second flow on the same wallet origin, for a partner that wants the client to get an Assetera\n * Wallet (a new one, or the one the client already has). The partner opens\n * `${walletUrl}${ONBOARD_PATH}?origin=<partner origin>&v=<version>&chain=<CAIP-2 chain id>[&add=1]` from a user\n * click. The pop-up checks the claimed origin against its partner list, signs the client in through SSO, runs the\n * wizard (accept the wallet terms, create the wallet) and then posts `onboarded` (or `onboard-cancelled`) to\n * `window.opener` with `targetOrigin` = the partner origin. `add=1` asks for one more wallet even when the client\n * already has one.\n *\n * After `onboarded` the pop-up STAYS OPEN and answers `request` messages for `personal_sign` by the onboarded\n * address (plus `eth_accounts` and `eth_chainId`), with the same `response` messages as `/connect`. That is how\n * the partner gets the ownership signature it needs to register the wallet with its own compliance service: the\n * wallet itself never calls a regulated service (ADR-0059 D3), and a second `window.open` after an asynchronous\n * step would be blocked by the browser. The partner closes the pop-up when it is done.\n *\n * The opener accepts messages only when `event.origin` is the wallet origin AND `event.source` is the pop-up\n * it opened. The wizard never returns a private key or a token, only the wallet address and signatures the\n * client approved.\n */\n\nexport const PROTOCOL_VERSION = 1 as const;\n\n/** The pop-up route on the wallet origin. */\nexport const CONNECT_PATH = \"/connect\";\n\n/** The onboarding wizard route on the wallet origin. */\nexport const ONBOARD_PATH = \"/onboard\";\n\n/** Every message carries this prefix in `type`, so both sides can ignore unrelated `postMessage` traffic. */\nexport const MESSAGE_PREFIX = \"assetera-wallet:\" as const;\n\n/**\n * The EIP-1193 methods the pop-up answers (ADR-0054 D3). Anything else is refused with 4200. Read-only chain\n * calls (`eth_call`, `eth_getBalance`, …) do not go through the pop-up; wagmi sends them to its own transports.\n */\nexport const SUPPORTED_METHODS = [\n \"eth_requestAccounts\",\n \"eth_accounts\",\n \"eth_chainId\",\n \"wallet_switchEthereumChain\",\n \"personal_sign\",\n \"eth_signTypedData_v4\",\n \"eth_sendTransaction\",\n] as const;\n\nexport type SupportedMethod = (typeof SUPPORTED_METHODS)[number];\n\nexport function isSupportedMethod(method: string): method is SupportedMethod {\n return (SUPPORTED_METHODS as readonly string[]).includes(method);\n}\n\n/** EIP-1193 / EIP-1474 error codes the pop-up uses. */\nexport const RpcErrorCode = {\n /** The client rejected the request in the pop-up. */\n UserRejected: 4001,\n /** Not connected yet (no `eth_requestAccounts` approved in this pop-up). */\n Unauthorized: 4100,\n /** The method is not in SUPPORTED_METHODS. */\n UnsupportedMethod: 4200,\n /** The pop-up closed, or the wallet session ended. */\n Disconnected: 4900,\n /** `wallet_switchEthereumChain` to a chain the wallet does not offer. */\n UnrecognizedChain: 4902,\n /** Malformed params. */\n InvalidParams: -32602,\n /** Anything unexpected inside the wallet. */\n Internal: -32603,\n} as const;\n\nexport type RpcErrorCode = (typeof RpcErrorCode)[keyof typeof RpcErrorCode];\n\nexport interface RpcError {\n code: number;\n message: string;\n data?: unknown;\n}\n\n// --- pop-up → opener ---------------------------------------------------------------------------------\n\n/** The pop-up is loaded and accepts requests from this opener. */\nexport interface ReadyMessage {\n type: `${typeof MESSAGE_PREFIX}ready`;\n v: typeof PROTOCOL_VERSION;\n /** Shown to the partner for diagnostics only; the partner must not rely on it for anything. */\n walletVersion?: string;\n}\n\n/** The answer to one `request`, matched by `id`. Exactly one of `result` / `error`. */\nexport type ResponseMessage =\n | { type: `${typeof MESSAGE_PREFIX}response`; v: typeof PROTOCOL_VERSION; id: string; result: unknown }\n | { type: `${typeof MESSAGE_PREFIX}response`; v: typeof PROTOCOL_VERSION; id: string; error: RpcError };\n\n/** EIP-1193 provider events, forwarded to the partner. */\nexport type EventMessage =\n | {\n type: `${typeof MESSAGE_PREFIX}event`;\n v: typeof PROTOCOL_VERSION;\n event: \"accountsChanged\";\n data: `0x${string}`[];\n }\n | {\n type: `${typeof MESSAGE_PREFIX}event`;\n v: typeof PROTOCOL_VERSION;\n event: \"chainChanged\";\n data: `0x${string}`;\n }\n | {\n type: `${typeof MESSAGE_PREFIX}event`;\n v: typeof PROTOCOL_VERSION;\n event: \"disconnect\";\n data: RpcError;\n };\n\n/**\n * The onboarding wizard finished: the client accepted the wallet terms and has an Assetera Wallet on `chain`.\n * `created` is `true` when the wallet was created in this run, `false` when the wizard returned the client's\n * existing wallet. The wallet is not registered with any compliance service; that is the partner's step.\n */\nexport interface OnboardedMessage {\n type: `${typeof MESSAGE_PREFIX}onboarded`;\n v: typeof PROTOCOL_VERSION;\n address: `0x${string}`;\n chain: string;\n created: boolean;\n /**\n * @deprecated Sent by wallet versions that registered the wallet themselves (before ADR-0059). Ignored.\n */\n status?: \"approved\" | \"pending\";\n}\n\n/** The onboarding wizard did not produce a wallet. `message` is optional diagnostics for the partner. */\nexport interface OnboardCancelledMessage {\n type: `${typeof MESSAGE_PREFIX}onboard-cancelled`;\n v: typeof PROTOCOL_VERSION;\n reason: \"user\" | \"refused\" | \"error\";\n message?: string;\n}\n\nexport type WalletToPartnerMessage =\n ReadyMessage | ResponseMessage | EventMessage | OnboardedMessage | OnboardCancelledMessage;\n\n// --- opener → pop-up ---------------------------------------------------------------------------------\n\nexport interface RequestMessage {\n type: `${typeof MESSAGE_PREFIX}request`;\n v: typeof PROTOCOL_VERSION;\n /** Unique per request within one connection; the response carries it back. */\n id: string;\n method: string;\n params?: unknown[] | Record<string, unknown>;\n}\n\n/** The partner disconnects (for example the user clicked \"Disconnect\" in the partner page). */\nexport interface DisconnectMessage {\n type: `${typeof MESSAGE_PREFIX}disconnect`;\n v: typeof PROTOCOL_VERSION;\n}\n\nexport type PartnerToWalletMessage = RequestMessage | DisconnectMessage;\n\n// --- guards ------------------------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction hasType(value: unknown, suffix: string): value is Record<string, unknown> {\n return isRecord(value) && value.type === `${MESSAGE_PREFIX}${suffix}` && value.v === PROTOCOL_VERSION;\n}\n\nexport function isReadyMessage(value: unknown): value is ReadyMessage {\n return hasType(value, \"ready\");\n}\n\nexport function isResponseMessage(value: unknown): value is ResponseMessage {\n return (\n hasType(value, \"response\") &&\n typeof value.id === \"string\" &&\n (\"result\" in value || (isRecord(value.error) && typeof value.error.code === \"number\"))\n );\n}\n\nexport function isEventMessage(value: unknown): value is EventMessage {\n return (\n hasType(value, \"event\") &&\n (value.event === \"accountsChanged\" || value.event === \"chainChanged\" || value.event === \"disconnect\")\n );\n}\n\nexport function isRequestMessage(value: unknown): value is RequestMessage {\n return hasType(value, \"request\") && typeof value.id === \"string\" && typeof value.method === \"string\";\n}\n\nexport function isDisconnectMessage(value: unknown): value is DisconnectMessage {\n return hasType(value, \"disconnect\");\n}\n\n/** `0x` followed by exactly 40 hexadecimal digits, the shape of an EVM address. */\nconst EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;\n\nexport function isOnboardedMessage(value: unknown): value is OnboardedMessage {\n return (\n hasType(value, \"onboarded\") &&\n typeof value.address === \"string\" &&\n EVM_ADDRESS_RE.test(value.address) &&\n typeof value.chain === \"string\" &&\n // `created` is new; an older wallet sent `status` instead and always created or reused a wallet.\n (typeof value.created === \"boolean\" || value.status === \"approved\" || value.status === \"pending\")\n );\n}\n\nexport function isOnboardCancelledMessage(value: unknown): value is OnboardCancelledMessage {\n return (\n hasType(value, \"onboard-cancelled\") &&\n (value.reason === \"user\" || value.reason === \"refused\" || value.reason === \"error\")\n );\n}\n\n/** A CAIP-2 EVM chain id, for example `eip155:80002` (Polygon Amoy) or `eip155:1` (mainnet). */\nexport function isCaip2EvmChain(value: string): boolean {\n return /^eip155:\\d{1,32}$/.test(value);\n}\n\n/** The URL the partner opens. `partnerOrigin` is `window.location.origin` of the partner page. */\nexport function connectUrl(walletUrl: string, partnerOrigin: string): string {\n const url = new URL(CONNECT_PATH, walletUrl);\n url.searchParams.set(\"origin\", partnerOrigin);\n url.searchParams.set(\"v\", String(PROTOCOL_VERSION));\n return url.toString();\n}\n\n/**\n * The URL the partner opens for the onboarding wizard. `partnerOrigin` is `window.location.origin` of the\n * partner page; `chain` is the CAIP-2 chain id the new wallet should be created on; `locale` is passed as `lang`\n * when the partner wants a specific wizard language.\n */\nexport function onboardUrl(\n walletUrl: string,\n partnerOrigin: string,\n options: { chain: string; locale?: string; add?: boolean },\n): string {\n const url = new URL(ONBOARD_PATH, walletUrl);\n url.searchParams.set(\"origin\", partnerOrigin);\n url.searchParams.set(\"v\", String(PROTOCOL_VERSION));\n url.searchParams.set(\"chain\", options.chain);\n if (options.locale !== undefined) url.searchParams.set(\"lang\", options.locale);\n if (options.add) url.searchParams.set(\"add\", \"1\");\n return url.toString();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/protocol.ts"],"names":[],"mappings":"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","file":"protocol.cjs","sourcesContent":["/**\n * The pop-up protocol between a partner page (the opener) and the Assetera Wallet (the pop-up) — ADR-0054 D3/D4.\n *\n * This file is the CONTRACT. The connector in this package speaks the opener side; AsseteraWalletFront's\n * `/connect` page speaks the pop-up side and imports these types from `@asseteragmbh/wallet-connector/protocol`.\n * Change it only in a backwards-compatible way, or bump `PROTOCOL_VERSION` and support both on the wallet side:\n * partner sites upgrade on their own schedule.\n *\n * ## The handshake\n *\n * 1. The partner opens `${walletUrl}${CONNECT_PATH}?origin=<partner origin>&v=<version>` from a user click.\n * 2. The pop-up checks the claimed origin against its allowlist (D4). If listed, it posts `ready` to\n * `window.opener` with `targetOrigin` = that origin. The browser delivers it ONLY if the opener really is\n * that origin, so a page cannot claim someone else's origin and still hear the answer.\n * 3. The opener waits for `ready` from the wallet origin, then sends `request`s with `targetOrigin` = the wallet\n * origin. The pop-up accepts a message only when `event.origin` is the allowed origin from step 2 AND\n * `event.source === window.opener`, and answers with `targetOrigin` = that origin. Nothing else is accepted.\n *\n * ## Sign-in hint\n *\n * A partner may tell the wallet how the client signed in at the partner, through the optional `signIn` URL\n * parameter (`SIGN_IN_HINTS`). The hint only names an identity provider: the wallet checks it against its own\n * list, may ignore it and then falls back to its own login page. The hint never carries a token, an identity or\n * any other credential.\n *\n * ## Lifetime\n *\n * The pop-up is not guaranteed to stay open. The wallet site may close the `/connect` pop-up after it connected\n * or answered a request. The provider keeps the last `accounts` and `chainId` it saw, so the partner page still\n * looks connected after the pop-up closes, and it opens the pop-up again on the next request from a user click.\n * (ADR-0054, \"the wallet tab must stay open\", no longer holds.)\n *\n * ## Onboarding\n *\n * Onboarding is a second flow on the same wallet origin, for a partner that wants the client to get an Assetera\n * Wallet (a new one, or the one the client already has). The partner opens\n * `${walletUrl}${ONBOARD_PATH}?origin=<partner origin>&v=<version>&chain=<CAIP-2 chain id>[&add=1]` from a user\n * click. The pop-up checks the claimed origin against its partner list, signs the client in through SSO, runs the\n * wizard (accept the wallet terms, create the wallet) and then posts `onboarded` (or `onboard-cancelled`) to\n * `window.opener` with `targetOrigin` = the partner origin. `add=1` asks for one more wallet even when the client\n * already has one.\n *\n * After `onboarded` the pop-up STAYS OPEN and answers `request` messages for `personal_sign` by the onboarded\n * address (plus `eth_accounts` and `eth_chainId`), with the same `response` messages as `/connect`. That is how\n * the partner gets the ownership signature it needs to register the wallet with its own compliance service: the\n * wallet itself never calls a regulated service (ADR-0059 D3), and a second `window.open` after an asynchronous\n * step would be blocked by the browser. The partner closes the pop-up when it is done.\n *\n * The opener accepts messages only when `event.origin` is the wallet origin AND `event.source` is the pop-up\n * it opened. The wizard never returns a private key or a token, only the wallet address and signatures the\n * client approved.\n *\n * ## Manage\n *\n * The partner can open `${walletUrl}${MANAGE_PATH}?origin=<partner origin>&v=<version>[&lang=<locale>][&signIn=<hint>]`\n * from a user click, so the client can see and change the wallet accounts and the wallet security (passkeys,\n * authenticator app, recovery codes). The pop-up checks the claimed origin against its partner list, posts\n * `ready` to `window.opener` (the same message as `/connect`) and then posts `security` messages. It never\n * answers `request` messages.\n */\n\nexport const PROTOCOL_VERSION = 1 as const;\n\n/** The pop-up route on the wallet origin. */\nexport const CONNECT_PATH = \"/connect\";\n\n/** The onboarding wizard route on the wallet origin. */\nexport const ONBOARD_PATH = \"/onboard\";\n\n/** The manage wallet route on the wallet origin. */\nexport const MANAGE_PATH = \"/manage\";\n\n/** The identity providers a partner can name in the `signIn` hint. */\nexport const SIGN_IN_HINTS = [\"assetera-marketplace\"] as const;\n\n/** A named identity provider the wallet may use for a silent sign-in. */\nexport type SignInHint = (typeof SIGN_IN_HINTS)[number];\n\n/** True when `value` is one of {@link SIGN_IN_HINTS}. */\nexport function isSignInHint(value: unknown): value is SignInHint {\n return (SIGN_IN_HINTS as readonly unknown[]).includes(value);\n}\n\n/** Every message carries this prefix in `type`, so both sides can ignore unrelated `postMessage` traffic. */\nexport const MESSAGE_PREFIX = \"assetera-wallet:\" as const;\n\n/**\n * The EIP-1193 methods the pop-up answers (ADR-0054 D3). Anything else is refused with 4200. Read-only chain\n * calls (`eth_call`, `eth_getBalance`, …) do not go through the pop-up; wagmi sends them to its own transports.\n */\nexport const SUPPORTED_METHODS = [\n \"eth_requestAccounts\",\n \"eth_accounts\",\n \"eth_chainId\",\n \"wallet_switchEthereumChain\",\n \"personal_sign\",\n \"eth_signTypedData_v4\",\n \"eth_sendTransaction\",\n] as const;\n\nexport type SupportedMethod = (typeof SUPPORTED_METHODS)[number];\n\nexport function isSupportedMethod(method: string): method is SupportedMethod {\n return (SUPPORTED_METHODS as readonly string[]).includes(method);\n}\n\n/** EIP-1193 / EIP-1474 error codes the pop-up uses. */\nexport const RpcErrorCode = {\n /** The client rejected the request in the pop-up. */\n UserRejected: 4001,\n /** Not connected yet (no `eth_requestAccounts` approved in this pop-up). */\n Unauthorized: 4100,\n /** The method is not in SUPPORTED_METHODS. */\n UnsupportedMethod: 4200,\n /** The pop-up closed, or the wallet session ended. */\n Disconnected: 4900,\n /** `wallet_switchEthereumChain` to a chain the wallet does not offer. */\n UnrecognizedChain: 4902,\n /** Malformed params. */\n InvalidParams: -32602,\n /** Anything unexpected inside the wallet. */\n Internal: -32603,\n} as const;\n\nexport type RpcErrorCode = (typeof RpcErrorCode)[keyof typeof RpcErrorCode];\n\nexport interface RpcError {\n code: number;\n message: string;\n data?: unknown;\n}\n\n// --- pop-up → opener ---------------------------------------------------------------------------------\n\n/** The pop-up is loaded and accepts requests from this opener. */\nexport interface ReadyMessage {\n type: `${typeof MESSAGE_PREFIX}ready`;\n v: typeof PROTOCOL_VERSION;\n /** Shown to the partner for diagnostics only; the partner must not rely on it for anything. */\n walletVersion?: string;\n}\n\n/** The answer to one `request`, matched by `id`. Exactly one of `result` / `error`. */\nexport type ResponseMessage =\n | { type: `${typeof MESSAGE_PREFIX}response`; v: typeof PROTOCOL_VERSION; id: string; result: unknown }\n | { type: `${typeof MESSAGE_PREFIX}response`; v: typeof PROTOCOL_VERSION; id: string; error: RpcError };\n\n/** EIP-1193 provider events, forwarded to the partner. */\nexport type EventMessage =\n | {\n type: `${typeof MESSAGE_PREFIX}event`;\n v: typeof PROTOCOL_VERSION;\n event: \"accountsChanged\";\n data: `0x${string}`[];\n }\n | {\n type: `${typeof MESSAGE_PREFIX}event`;\n v: typeof PROTOCOL_VERSION;\n event: \"chainChanged\";\n data: `0x${string}`;\n }\n | {\n type: `${typeof MESSAGE_PREFIX}event`;\n v: typeof PROTOCOL_VERSION;\n event: \"disconnect\";\n data: RpcError;\n };\n\n/**\n * How well the client's Assetera Wallet is protected. The values are the ones the wallet site shows:\n *\n * - `add-factor`: there is no passkey and no authenticator app yet.\n * - `save-codes`: recovery codes exist, but the client has not confirmed saving them.\n * - `create-codes`: a factor exists, but there are no recovery codes.\n * - `protected`: a factor exists and the recovery codes are saved.\n * - `unknown`: the wallet could not read the state.\n */\nexport type WalletProtection = \"unknown\" | \"add-factor\" | \"save-codes\" | \"create-codes\" | \"protected\";\n\n/** The wallet security status sent by a manage (or connect) pop-up. */\nexport interface WalletSecurityStatus {\n /** Overall result, the same values the wallet site shows. */\n protection: WalletProtection;\n /** Passkeys registered for signing (Dynamic step-up), not sign-in factors. */\n passkeys: number;\n /** Authenticator apps (TOTP) registered for signing (Dynamic step-up). */\n authenticatorApps: number;\n}\n\n/**\n * The wallet reports the security status while a pop-up is open. The partner cannot ask for it. It never\n * carries a token, an identity or a credential.\n */\nexport interface SecurityMessage {\n type: `${typeof MESSAGE_PREFIX}security`;\n v: typeof PROTOCOL_VERSION;\n data: WalletSecurityStatus;\n}\n\n/**\n * The onboarding wizard finished: the client accepted the wallet terms and has an Assetera Wallet on `chain`.\n * `created` is `true` when the wallet was created in this run, `false` when the wizard returned the client's\n * existing wallet. The wallet is not registered with any compliance service; that is the partner's step.\n */\nexport interface OnboardedMessage {\n type: `${typeof MESSAGE_PREFIX}onboarded`;\n v: typeof PROTOCOL_VERSION;\n address: `0x${string}`;\n chain: string;\n created: boolean;\n /**\n * @deprecated Sent by wallet versions that registered the wallet themselves (before ADR-0059). Ignored.\n */\n status?: \"approved\" | \"pending\";\n}\n\n/** The onboarding wizard did not produce a wallet. `message` is optional diagnostics for the partner. */\nexport interface OnboardCancelledMessage {\n type: `${typeof MESSAGE_PREFIX}onboard-cancelled`;\n v: typeof PROTOCOL_VERSION;\n reason: \"user\" | \"refused\" | \"error\";\n message?: string;\n}\n\nexport type WalletToPartnerMessage =\n | ReadyMessage\n | ResponseMessage\n | EventMessage\n | SecurityMessage\n | OnboardedMessage\n | OnboardCancelledMessage;\n\n// --- opener → pop-up ---------------------------------------------------------------------------------\n\nexport interface RequestMessage {\n type: `${typeof MESSAGE_PREFIX}request`;\n v: typeof PROTOCOL_VERSION;\n /** Unique per request within one connection; the response carries it back. */\n id: string;\n method: string;\n params?: unknown[] | Record<string, unknown>;\n}\n\n/** The partner disconnects (for example the user clicked \"Disconnect\" in the partner page). */\nexport interface DisconnectMessage {\n type: `${typeof MESSAGE_PREFIX}disconnect`;\n v: typeof PROTOCOL_VERSION;\n}\n\nexport type PartnerToWalletMessage = RequestMessage | DisconnectMessage;\n\n// --- guards ------------------------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction hasType(value: unknown, suffix: string): value is Record<string, unknown> {\n return isRecord(value) && value.type === `${MESSAGE_PREFIX}${suffix}` && value.v === PROTOCOL_VERSION;\n}\n\nexport function isReadyMessage(value: unknown): value is ReadyMessage {\n return hasType(value, \"ready\");\n}\n\nexport function isResponseMessage(value: unknown): value is ResponseMessage {\n return (\n hasType(value, \"response\") &&\n typeof value.id === \"string\" &&\n (\"result\" in value || (isRecord(value.error) && typeof value.error.code === \"number\"))\n );\n}\n\nexport function isEventMessage(value: unknown): value is EventMessage {\n return (\n hasType(value, \"event\") &&\n (value.event === \"accountsChanged\" || value.event === \"chainChanged\" || value.event === \"disconnect\")\n );\n}\n\nconst WALLET_PROTECTIONS: readonly WalletProtection[] = [\n \"unknown\",\n \"add-factor\",\n \"save-codes\",\n \"create-codes\",\n \"protected\",\n];\n\n/** A factor count: a whole number, zero or more. */\nfunction isCount(value: unknown): value is number {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 0;\n}\n\n/** True for a `security` message with a known `protection` value and whole, non-negative factor counts. */\nexport function isSecurityMessage(value: unknown): value is SecurityMessage {\n if (!hasType(value, \"security\")) return false;\n const data = value.data;\n return (\n isRecord(data) &&\n typeof data.protection === \"string\" &&\n (WALLET_PROTECTIONS as readonly string[]).includes(data.protection) &&\n isCount(data.passkeys) &&\n isCount(data.authenticatorApps)\n );\n}\n\nexport function isRequestMessage(value: unknown): value is RequestMessage {\n return hasType(value, \"request\") && typeof value.id === \"string\" && typeof value.method === \"string\";\n}\n\nexport function isDisconnectMessage(value: unknown): value is DisconnectMessage {\n return hasType(value, \"disconnect\");\n}\n\n/** `0x` followed by exactly 40 hexadecimal digits, the shape of an EVM address. */\nconst EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;\n\nexport function isOnboardedMessage(value: unknown): value is OnboardedMessage {\n return (\n hasType(value, \"onboarded\") &&\n typeof value.address === \"string\" &&\n EVM_ADDRESS_RE.test(value.address) &&\n typeof value.chain === \"string\" &&\n // `created` is new; an older wallet sent `status` instead and always created or reused a wallet.\n (typeof value.created === \"boolean\" || value.status === \"approved\" || value.status === \"pending\")\n );\n}\n\nexport function isOnboardCancelledMessage(value: unknown): value is OnboardCancelledMessage {\n return (\n hasType(value, \"onboard-cancelled\") &&\n (value.reason === \"user\" || value.reason === \"refused\" || value.reason === \"error\")\n );\n}\n\n/** A CAIP-2 EVM chain id, for example `eip155:80002` (Polygon Amoy) or `eip155:1` (mainnet). */\nexport function isCaip2EvmChain(value: string): boolean {\n return /^eip155:\\d{1,32}$/.test(value);\n}\n\n/**\n * The URL the partner opens. `partnerOrigin` is `window.location.origin` of the partner page. `signIn` adds the\n * optional sign-in hint; it is only a hint and the wallet may ignore it.\n */\nexport function connectUrl(walletUrl: string, partnerOrigin: string, signIn?: SignInHint): string {\n const url = new URL(CONNECT_PATH, walletUrl);\n url.searchParams.set(\"origin\", partnerOrigin);\n url.searchParams.set(\"v\", String(PROTOCOL_VERSION));\n if (signIn !== undefined) url.searchParams.set(\"signIn\", signIn);\n return url.toString();\n}\n\n/**\n * The URL the partner opens for the onboarding wizard. `partnerOrigin` is `window.location.origin` of the\n * partner page; `chain` is the CAIP-2 chain id the new wallet should be created on; `locale` is passed as `lang`\n * when the partner wants a specific wizard language. `signIn` adds the optional sign-in hint; it is only a hint\n * and the wallet may ignore it.\n */\nexport function onboardUrl(\n walletUrl: string,\n partnerOrigin: string,\n options: { chain: string; locale?: string; add?: boolean; signIn?: SignInHint },\n): string {\n const url = new URL(ONBOARD_PATH, walletUrl);\n url.searchParams.set(\"origin\", partnerOrigin);\n url.searchParams.set(\"v\", String(PROTOCOL_VERSION));\n url.searchParams.set(\"chain\", options.chain);\n if (options.locale !== undefined) url.searchParams.set(\"lang\", options.locale);\n if (options.add) url.searchParams.set(\"add\", \"1\");\n if (options.signIn !== undefined) url.searchParams.set(\"signIn\", options.signIn);\n return url.toString();\n}\n\n/**\n * The URL the partner opens to manage the wallet. `partnerOrigin` is `window.location.origin` of the partner\n * page. `locale` is passed as `lang` when the partner wants a specific language. `signIn` adds the optional\n * sign-in hint; it is only a hint and the wallet may ignore it.\n */\nexport function manageUrl(\n walletUrl: string,\n partnerOrigin: string,\n options: { locale?: string; signIn?: SignInHint } = {},\n): string {\n const url = new URL(MANAGE_PATH, walletUrl);\n url.searchParams.set(\"origin\", partnerOrigin);\n url.searchParams.set(\"v\", String(PROTOCOL_VERSION));\n if (options.locale !== undefined) url.searchParams.set(\"lang\", options.locale);\n if (options.signIn !== undefined) url.searchParams.set(\"signIn\", options.signIn);\n return url.toString();\n}\n"]}
|
package/dist/protocol.d.cts
CHANGED
|
@@ -16,10 +16,19 @@
|
|
|
16
16
|
* origin. The pop-up accepts a message only when `event.origin` is the allowed origin from step 2 AND
|
|
17
17
|
* `event.source === window.opener`, and answers with `targetOrigin` = that origin. Nothing else is accepted.
|
|
18
18
|
*
|
|
19
|
+
* ## Sign-in hint
|
|
20
|
+
*
|
|
21
|
+
* A partner may tell the wallet how the client signed in at the partner, through the optional `signIn` URL
|
|
22
|
+
* parameter (`SIGN_IN_HINTS`). The hint only names an identity provider: the wallet checks it against its own
|
|
23
|
+
* list, may ignore it and then falls back to its own login page. The hint never carries a token, an identity or
|
|
24
|
+
* any other credential.
|
|
25
|
+
*
|
|
19
26
|
* ## Lifetime
|
|
20
27
|
*
|
|
21
|
-
* The pop-up
|
|
22
|
-
*
|
|
28
|
+
* The pop-up is not guaranteed to stay open. The wallet site may close the `/connect` pop-up after it connected
|
|
29
|
+
* or answered a request. The provider keeps the last `accounts` and `chainId` it saw, so the partner page still
|
|
30
|
+
* looks connected after the pop-up closes, and it opens the pop-up again on the next request from a user click.
|
|
31
|
+
* (ADR-0054, "the wallet tab must stay open", no longer holds.)
|
|
23
32
|
*
|
|
24
33
|
* ## Onboarding
|
|
25
34
|
*
|
|
@@ -40,12 +49,28 @@
|
|
|
40
49
|
* The opener accepts messages only when `event.origin` is the wallet origin AND `event.source` is the pop-up
|
|
41
50
|
* it opened. The wizard never returns a private key or a token, only the wallet address and signatures the
|
|
42
51
|
* client approved.
|
|
52
|
+
*
|
|
53
|
+
* ## Manage
|
|
54
|
+
*
|
|
55
|
+
* The partner can open `${walletUrl}${MANAGE_PATH}?origin=<partner origin>&v=<version>[&lang=<locale>][&signIn=<hint>]`
|
|
56
|
+
* from a user click, so the client can see and change the wallet accounts and the wallet security (passkeys,
|
|
57
|
+
* authenticator app, recovery codes). The pop-up checks the claimed origin against its partner list, posts
|
|
58
|
+
* `ready` to `window.opener` (the same message as `/connect`) and then posts `security` messages. It never
|
|
59
|
+
* answers `request` messages.
|
|
43
60
|
*/
|
|
44
61
|
declare const PROTOCOL_VERSION: 1;
|
|
45
62
|
/** The pop-up route on the wallet origin. */
|
|
46
63
|
declare const CONNECT_PATH = "/connect";
|
|
47
64
|
/** The onboarding wizard route on the wallet origin. */
|
|
48
65
|
declare const ONBOARD_PATH = "/onboard";
|
|
66
|
+
/** The manage wallet route on the wallet origin. */
|
|
67
|
+
declare const MANAGE_PATH = "/manage";
|
|
68
|
+
/** The identity providers a partner can name in the `signIn` hint. */
|
|
69
|
+
declare const SIGN_IN_HINTS: readonly ["assetera-marketplace"];
|
|
70
|
+
/** A named identity provider the wallet may use for a silent sign-in. */
|
|
71
|
+
type SignInHint = (typeof SIGN_IN_HINTS)[number];
|
|
72
|
+
/** True when `value` is one of {@link SIGN_IN_HINTS}. */
|
|
73
|
+
declare function isSignInHint(value: unknown): value is SignInHint;
|
|
49
74
|
/** Every message carries this prefix in `type`, so both sides can ignore unrelated `postMessage` traffic. */
|
|
50
75
|
declare const MESSAGE_PREFIX: "assetera-wallet:";
|
|
51
76
|
/**
|
|
@@ -114,6 +139,34 @@ type EventMessage = {
|
|
|
114
139
|
event: "disconnect";
|
|
115
140
|
data: RpcError;
|
|
116
141
|
};
|
|
142
|
+
/**
|
|
143
|
+
* How well the client's Assetera Wallet is protected. The values are the ones the wallet site shows:
|
|
144
|
+
*
|
|
145
|
+
* - `add-factor`: there is no passkey and no authenticator app yet.
|
|
146
|
+
* - `save-codes`: recovery codes exist, but the client has not confirmed saving them.
|
|
147
|
+
* - `create-codes`: a factor exists, but there are no recovery codes.
|
|
148
|
+
* - `protected`: a factor exists and the recovery codes are saved.
|
|
149
|
+
* - `unknown`: the wallet could not read the state.
|
|
150
|
+
*/
|
|
151
|
+
type WalletProtection = "unknown" | "add-factor" | "save-codes" | "create-codes" | "protected";
|
|
152
|
+
/** The wallet security status sent by a manage (or connect) pop-up. */
|
|
153
|
+
interface WalletSecurityStatus {
|
|
154
|
+
/** Overall result, the same values the wallet site shows. */
|
|
155
|
+
protection: WalletProtection;
|
|
156
|
+
/** Passkeys registered for signing (Dynamic step-up), not sign-in factors. */
|
|
157
|
+
passkeys: number;
|
|
158
|
+
/** Authenticator apps (TOTP) registered for signing (Dynamic step-up). */
|
|
159
|
+
authenticatorApps: number;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The wallet reports the security status while a pop-up is open. The partner cannot ask for it. It never
|
|
163
|
+
* carries a token, an identity or a credential.
|
|
164
|
+
*/
|
|
165
|
+
interface SecurityMessage {
|
|
166
|
+
type: `${typeof MESSAGE_PREFIX}security`;
|
|
167
|
+
v: typeof PROTOCOL_VERSION;
|
|
168
|
+
data: WalletSecurityStatus;
|
|
169
|
+
}
|
|
117
170
|
/**
|
|
118
171
|
* The onboarding wizard finished: the client accepted the wallet terms and has an Assetera Wallet on `chain`.
|
|
119
172
|
* `created` is `true` when the wallet was created in this run, `false` when the wizard returned the client's
|
|
@@ -137,7 +190,7 @@ interface OnboardCancelledMessage {
|
|
|
137
190
|
reason: "user" | "refused" | "error";
|
|
138
191
|
message?: string;
|
|
139
192
|
}
|
|
140
|
-
type WalletToPartnerMessage = ReadyMessage | ResponseMessage | EventMessage | OnboardedMessage | OnboardCancelledMessage;
|
|
193
|
+
type WalletToPartnerMessage = ReadyMessage | ResponseMessage | EventMessage | SecurityMessage | OnboardedMessage | OnboardCancelledMessage;
|
|
141
194
|
interface RequestMessage {
|
|
142
195
|
type: `${typeof MESSAGE_PREFIX}request`;
|
|
143
196
|
v: typeof PROTOCOL_VERSION;
|
|
@@ -155,23 +208,39 @@ type PartnerToWalletMessage = RequestMessage | DisconnectMessage;
|
|
|
155
208
|
declare function isReadyMessage(value: unknown): value is ReadyMessage;
|
|
156
209
|
declare function isResponseMessage(value: unknown): value is ResponseMessage;
|
|
157
210
|
declare function isEventMessage(value: unknown): value is EventMessage;
|
|
211
|
+
/** True for a `security` message with a known `protection` value and whole, non-negative factor counts. */
|
|
212
|
+
declare function isSecurityMessage(value: unknown): value is SecurityMessage;
|
|
158
213
|
declare function isRequestMessage(value: unknown): value is RequestMessage;
|
|
159
214
|
declare function isDisconnectMessage(value: unknown): value is DisconnectMessage;
|
|
160
215
|
declare function isOnboardedMessage(value: unknown): value is OnboardedMessage;
|
|
161
216
|
declare function isOnboardCancelledMessage(value: unknown): value is OnboardCancelledMessage;
|
|
162
217
|
/** A CAIP-2 EVM chain id, for example `eip155:80002` (Polygon Amoy) or `eip155:1` (mainnet). */
|
|
163
218
|
declare function isCaip2EvmChain(value: string): boolean;
|
|
164
|
-
/**
|
|
165
|
-
|
|
219
|
+
/**
|
|
220
|
+
* The URL the partner opens. `partnerOrigin` is `window.location.origin` of the partner page. `signIn` adds the
|
|
221
|
+
* optional sign-in hint; it is only a hint and the wallet may ignore it.
|
|
222
|
+
*/
|
|
223
|
+
declare function connectUrl(walletUrl: string, partnerOrigin: string, signIn?: SignInHint): string;
|
|
166
224
|
/**
|
|
167
225
|
* The URL the partner opens for the onboarding wizard. `partnerOrigin` is `window.location.origin` of the
|
|
168
226
|
* partner page; `chain` is the CAIP-2 chain id the new wallet should be created on; `locale` is passed as `lang`
|
|
169
|
-
* when the partner wants a specific wizard language.
|
|
227
|
+
* when the partner wants a specific wizard language. `signIn` adds the optional sign-in hint; it is only a hint
|
|
228
|
+
* and the wallet may ignore it.
|
|
170
229
|
*/
|
|
171
230
|
declare function onboardUrl(walletUrl: string, partnerOrigin: string, options: {
|
|
172
231
|
chain: string;
|
|
173
232
|
locale?: string;
|
|
174
233
|
add?: boolean;
|
|
234
|
+
signIn?: SignInHint;
|
|
235
|
+
}): string;
|
|
236
|
+
/**
|
|
237
|
+
* The URL the partner opens to manage the wallet. `partnerOrigin` is `window.location.origin` of the partner
|
|
238
|
+
* page. `locale` is passed as `lang` when the partner wants a specific language. `signIn` adds the optional
|
|
239
|
+
* sign-in hint; it is only a hint and the wallet may ignore it.
|
|
240
|
+
*/
|
|
241
|
+
declare function manageUrl(walletUrl: string, partnerOrigin: string, options?: {
|
|
242
|
+
locale?: string;
|
|
243
|
+
signIn?: SignInHint;
|
|
175
244
|
}): string;
|
|
176
245
|
|
|
177
|
-
export { CONNECT_PATH, type DisconnectMessage, type EventMessage, MESSAGE_PREFIX, ONBOARD_PATH, type OnboardCancelledMessage, type OnboardedMessage, PROTOCOL_VERSION, type PartnerToWalletMessage, type ReadyMessage, type RequestMessage, type ResponseMessage, type RpcError, RpcErrorCode, SUPPORTED_METHODS, type SupportedMethod, type WalletToPartnerMessage, connectUrl, isCaip2EvmChain, isDisconnectMessage, isEventMessage, isOnboardCancelledMessage, isOnboardedMessage, isReadyMessage, isRequestMessage, isResponseMessage, isSupportedMethod, onboardUrl };
|
|
246
|
+
export { CONNECT_PATH, type DisconnectMessage, type EventMessage, MANAGE_PATH, MESSAGE_PREFIX, ONBOARD_PATH, type OnboardCancelledMessage, type OnboardedMessage, PROTOCOL_VERSION, type PartnerToWalletMessage, type ReadyMessage, type RequestMessage, type ResponseMessage, type RpcError, RpcErrorCode, SIGN_IN_HINTS, SUPPORTED_METHODS, type SecurityMessage, type SignInHint, type SupportedMethod, type WalletProtection, type WalletSecurityStatus, type WalletToPartnerMessage, connectUrl, isCaip2EvmChain, isDisconnectMessage, isEventMessage, isOnboardCancelledMessage, isOnboardedMessage, isReadyMessage, isRequestMessage, isResponseMessage, isSecurityMessage, isSignInHint, isSupportedMethod, manageUrl, onboardUrl };
|
package/dist/protocol.d.ts
CHANGED
|
@@ -16,10 +16,19 @@
|
|
|
16
16
|
* origin. The pop-up accepts a message only when `event.origin` is the allowed origin from step 2 AND
|
|
17
17
|
* `event.source === window.opener`, and answers with `targetOrigin` = that origin. Nothing else is accepted.
|
|
18
18
|
*
|
|
19
|
+
* ## Sign-in hint
|
|
20
|
+
*
|
|
21
|
+
* A partner may tell the wallet how the client signed in at the partner, through the optional `signIn` URL
|
|
22
|
+
* parameter (`SIGN_IN_HINTS`). The hint only names an identity provider: the wallet checks it against its own
|
|
23
|
+
* list, may ignore it and then falls back to its own login page. The hint never carries a token, an identity or
|
|
24
|
+
* any other credential.
|
|
25
|
+
*
|
|
19
26
|
* ## Lifetime
|
|
20
27
|
*
|
|
21
|
-
* The pop-up
|
|
22
|
-
*
|
|
28
|
+
* The pop-up is not guaranteed to stay open. The wallet site may close the `/connect` pop-up after it connected
|
|
29
|
+
* or answered a request. The provider keeps the last `accounts` and `chainId` it saw, so the partner page still
|
|
30
|
+
* looks connected after the pop-up closes, and it opens the pop-up again on the next request from a user click.
|
|
31
|
+
* (ADR-0054, "the wallet tab must stay open", no longer holds.)
|
|
23
32
|
*
|
|
24
33
|
* ## Onboarding
|
|
25
34
|
*
|
|
@@ -40,12 +49,28 @@
|
|
|
40
49
|
* The opener accepts messages only when `event.origin` is the wallet origin AND `event.source` is the pop-up
|
|
41
50
|
* it opened. The wizard never returns a private key or a token, only the wallet address and signatures the
|
|
42
51
|
* client approved.
|
|
52
|
+
*
|
|
53
|
+
* ## Manage
|
|
54
|
+
*
|
|
55
|
+
* The partner can open `${walletUrl}${MANAGE_PATH}?origin=<partner origin>&v=<version>[&lang=<locale>][&signIn=<hint>]`
|
|
56
|
+
* from a user click, so the client can see and change the wallet accounts and the wallet security (passkeys,
|
|
57
|
+
* authenticator app, recovery codes). The pop-up checks the claimed origin against its partner list, posts
|
|
58
|
+
* `ready` to `window.opener` (the same message as `/connect`) and then posts `security` messages. It never
|
|
59
|
+
* answers `request` messages.
|
|
43
60
|
*/
|
|
44
61
|
declare const PROTOCOL_VERSION: 1;
|
|
45
62
|
/** The pop-up route on the wallet origin. */
|
|
46
63
|
declare const CONNECT_PATH = "/connect";
|
|
47
64
|
/** The onboarding wizard route on the wallet origin. */
|
|
48
65
|
declare const ONBOARD_PATH = "/onboard";
|
|
66
|
+
/** The manage wallet route on the wallet origin. */
|
|
67
|
+
declare const MANAGE_PATH = "/manage";
|
|
68
|
+
/** The identity providers a partner can name in the `signIn` hint. */
|
|
69
|
+
declare const SIGN_IN_HINTS: readonly ["assetera-marketplace"];
|
|
70
|
+
/** A named identity provider the wallet may use for a silent sign-in. */
|
|
71
|
+
type SignInHint = (typeof SIGN_IN_HINTS)[number];
|
|
72
|
+
/** True when `value` is one of {@link SIGN_IN_HINTS}. */
|
|
73
|
+
declare function isSignInHint(value: unknown): value is SignInHint;
|
|
49
74
|
/** Every message carries this prefix in `type`, so both sides can ignore unrelated `postMessage` traffic. */
|
|
50
75
|
declare const MESSAGE_PREFIX: "assetera-wallet:";
|
|
51
76
|
/**
|
|
@@ -114,6 +139,34 @@ type EventMessage = {
|
|
|
114
139
|
event: "disconnect";
|
|
115
140
|
data: RpcError;
|
|
116
141
|
};
|
|
142
|
+
/**
|
|
143
|
+
* How well the client's Assetera Wallet is protected. The values are the ones the wallet site shows:
|
|
144
|
+
*
|
|
145
|
+
* - `add-factor`: there is no passkey and no authenticator app yet.
|
|
146
|
+
* - `save-codes`: recovery codes exist, but the client has not confirmed saving them.
|
|
147
|
+
* - `create-codes`: a factor exists, but there are no recovery codes.
|
|
148
|
+
* - `protected`: a factor exists and the recovery codes are saved.
|
|
149
|
+
* - `unknown`: the wallet could not read the state.
|
|
150
|
+
*/
|
|
151
|
+
type WalletProtection = "unknown" | "add-factor" | "save-codes" | "create-codes" | "protected";
|
|
152
|
+
/** The wallet security status sent by a manage (or connect) pop-up. */
|
|
153
|
+
interface WalletSecurityStatus {
|
|
154
|
+
/** Overall result, the same values the wallet site shows. */
|
|
155
|
+
protection: WalletProtection;
|
|
156
|
+
/** Passkeys registered for signing (Dynamic step-up), not sign-in factors. */
|
|
157
|
+
passkeys: number;
|
|
158
|
+
/** Authenticator apps (TOTP) registered for signing (Dynamic step-up). */
|
|
159
|
+
authenticatorApps: number;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The wallet reports the security status while a pop-up is open. The partner cannot ask for it. It never
|
|
163
|
+
* carries a token, an identity or a credential.
|
|
164
|
+
*/
|
|
165
|
+
interface SecurityMessage {
|
|
166
|
+
type: `${typeof MESSAGE_PREFIX}security`;
|
|
167
|
+
v: typeof PROTOCOL_VERSION;
|
|
168
|
+
data: WalletSecurityStatus;
|
|
169
|
+
}
|
|
117
170
|
/**
|
|
118
171
|
* The onboarding wizard finished: the client accepted the wallet terms and has an Assetera Wallet on `chain`.
|
|
119
172
|
* `created` is `true` when the wallet was created in this run, `false` when the wizard returned the client's
|
|
@@ -137,7 +190,7 @@ interface OnboardCancelledMessage {
|
|
|
137
190
|
reason: "user" | "refused" | "error";
|
|
138
191
|
message?: string;
|
|
139
192
|
}
|
|
140
|
-
type WalletToPartnerMessage = ReadyMessage | ResponseMessage | EventMessage | OnboardedMessage | OnboardCancelledMessage;
|
|
193
|
+
type WalletToPartnerMessage = ReadyMessage | ResponseMessage | EventMessage | SecurityMessage | OnboardedMessage | OnboardCancelledMessage;
|
|
141
194
|
interface RequestMessage {
|
|
142
195
|
type: `${typeof MESSAGE_PREFIX}request`;
|
|
143
196
|
v: typeof PROTOCOL_VERSION;
|
|
@@ -155,23 +208,39 @@ type PartnerToWalletMessage = RequestMessage | DisconnectMessage;
|
|
|
155
208
|
declare function isReadyMessage(value: unknown): value is ReadyMessage;
|
|
156
209
|
declare function isResponseMessage(value: unknown): value is ResponseMessage;
|
|
157
210
|
declare function isEventMessage(value: unknown): value is EventMessage;
|
|
211
|
+
/** True for a `security` message with a known `protection` value and whole, non-negative factor counts. */
|
|
212
|
+
declare function isSecurityMessage(value: unknown): value is SecurityMessage;
|
|
158
213
|
declare function isRequestMessage(value: unknown): value is RequestMessage;
|
|
159
214
|
declare function isDisconnectMessage(value: unknown): value is DisconnectMessage;
|
|
160
215
|
declare function isOnboardedMessage(value: unknown): value is OnboardedMessage;
|
|
161
216
|
declare function isOnboardCancelledMessage(value: unknown): value is OnboardCancelledMessage;
|
|
162
217
|
/** A CAIP-2 EVM chain id, for example `eip155:80002` (Polygon Amoy) or `eip155:1` (mainnet). */
|
|
163
218
|
declare function isCaip2EvmChain(value: string): boolean;
|
|
164
|
-
/**
|
|
165
|
-
|
|
219
|
+
/**
|
|
220
|
+
* The URL the partner opens. `partnerOrigin` is `window.location.origin` of the partner page. `signIn` adds the
|
|
221
|
+
* optional sign-in hint; it is only a hint and the wallet may ignore it.
|
|
222
|
+
*/
|
|
223
|
+
declare function connectUrl(walletUrl: string, partnerOrigin: string, signIn?: SignInHint): string;
|
|
166
224
|
/**
|
|
167
225
|
* The URL the partner opens for the onboarding wizard. `partnerOrigin` is `window.location.origin` of the
|
|
168
226
|
* partner page; `chain` is the CAIP-2 chain id the new wallet should be created on; `locale` is passed as `lang`
|
|
169
|
-
* when the partner wants a specific wizard language.
|
|
227
|
+
* when the partner wants a specific wizard language. `signIn` adds the optional sign-in hint; it is only a hint
|
|
228
|
+
* and the wallet may ignore it.
|
|
170
229
|
*/
|
|
171
230
|
declare function onboardUrl(walletUrl: string, partnerOrigin: string, options: {
|
|
172
231
|
chain: string;
|
|
173
232
|
locale?: string;
|
|
174
233
|
add?: boolean;
|
|
234
|
+
signIn?: SignInHint;
|
|
235
|
+
}): string;
|
|
236
|
+
/**
|
|
237
|
+
* The URL the partner opens to manage the wallet. `partnerOrigin` is `window.location.origin` of the partner
|
|
238
|
+
* page. `locale` is passed as `lang` when the partner wants a specific language. `signIn` adds the optional
|
|
239
|
+
* sign-in hint; it is only a hint and the wallet may ignore it.
|
|
240
|
+
*/
|
|
241
|
+
declare function manageUrl(walletUrl: string, partnerOrigin: string, options?: {
|
|
242
|
+
locale?: string;
|
|
243
|
+
signIn?: SignInHint;
|
|
175
244
|
}): string;
|
|
176
245
|
|
|
177
|
-
export { CONNECT_PATH, type DisconnectMessage, type EventMessage, MESSAGE_PREFIX, ONBOARD_PATH, type OnboardCancelledMessage, type OnboardedMessage, PROTOCOL_VERSION, type PartnerToWalletMessage, type ReadyMessage, type RequestMessage, type ResponseMessage, type RpcError, RpcErrorCode, SUPPORTED_METHODS, type SupportedMethod, type WalletToPartnerMessage, connectUrl, isCaip2EvmChain, isDisconnectMessage, isEventMessage, isOnboardCancelledMessage, isOnboardedMessage, isReadyMessage, isRequestMessage, isResponseMessage, isSupportedMethod, onboardUrl };
|
|
246
|
+
export { CONNECT_PATH, type DisconnectMessage, type EventMessage, MANAGE_PATH, MESSAGE_PREFIX, ONBOARD_PATH, type OnboardCancelledMessage, type OnboardedMessage, PROTOCOL_VERSION, type PartnerToWalletMessage, type ReadyMessage, type RequestMessage, type ResponseMessage, type RpcError, RpcErrorCode, SIGN_IN_HINTS, SUPPORTED_METHODS, type SecurityMessage, type SignInHint, type SupportedMethod, type WalletProtection, type WalletSecurityStatus, type WalletToPartnerMessage, connectUrl, isCaip2EvmChain, isDisconnectMessage, isEventMessage, isOnboardCancelledMessage, isOnboardedMessage, isReadyMessage, isRequestMessage, isResponseMessage, isSecurityMessage, isSignInHint, isSupportedMethod, manageUrl, onboardUrl };
|
package/dist/protocol.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { CONNECT_PATH, MESSAGE_PREFIX, ONBOARD_PATH, PROTOCOL_VERSION, RpcErrorCode, SUPPORTED_METHODS, connectUrl, isCaip2EvmChain, isDisconnectMessage, isEventMessage, isOnboardCancelledMessage, isOnboardedMessage, isReadyMessage, isRequestMessage, isResponseMessage, isSupportedMethod, onboardUrl } from './chunk-
|
|
1
|
+
export { CONNECT_PATH, MANAGE_PATH, MESSAGE_PREFIX, ONBOARD_PATH, PROTOCOL_VERSION, RpcErrorCode, SIGN_IN_HINTS, SUPPORTED_METHODS, connectUrl, isCaip2EvmChain, isDisconnectMessage, isEventMessage, isOnboardCancelledMessage, isOnboardedMessage, isReadyMessage, isRequestMessage, isResponseMessage, isSecurityMessage, isSignInHint, isSupportedMethod, manageUrl, onboardUrl } from './chunk-H7PEM735.js';
|
|
2
2
|
//# sourceMappingURL=protocol.js.map
|
|
3
3
|
//# sourceMappingURL=protocol.js.map
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
import { WalletSecurityStatus, SignInHint } from './protocol.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EIP-1193 provider for the Assetera Wallet pop-up — the opener side of the ADR-0054 D3/D4 protocol.
|
|
5
|
+
*
|
|
6
|
+
* The provider owns a single pop-up (`window.open(connectUrl(...), "assetera-wallet", ...)`) and speaks the
|
|
7
|
+
* wire format defined in `./protocol`. It never touches Dynamic, React, wagmi or viem, so a partner can use it
|
|
8
|
+
* on its own or through the wagmi / RainbowKit adapters in this package.
|
|
9
|
+
*/
|
|
10
|
+
|
|
1
11
|
/** Arguments accepted by `request`, mirroring EIP-1193. */
|
|
2
12
|
interface RequestArguments {
|
|
3
13
|
method: string;
|
|
4
14
|
params?: unknown[] | Record<string, unknown>;
|
|
5
15
|
}
|
|
6
|
-
/** EIP-1193 provider events emitted by the pop-up. */
|
|
7
|
-
type ProviderEvent = "accountsChanged" | "chainChanged" | "connect" | "disconnect";
|
|
16
|
+
/** EIP-1193 provider events emitted by the pop-up, plus the wallet security status. */
|
|
17
|
+
type ProviderEvent = "accountsChanged" | "chainChanged" | "connect" | "disconnect" | "assetera_security";
|
|
8
18
|
/**
|
|
9
19
|
* Listener shape for EIP-1193 provider events. `never[]` accepts a listener with any concrete parameter list
|
|
10
20
|
* (for example wagmi's `(accounts: string[]) => void`), while internal emission stays type-safe via a cast.
|
|
@@ -16,15 +26,22 @@ interface AsseteraWalletProvider {
|
|
|
16
26
|
on(event: ProviderEvent, listener: ProviderListener): void;
|
|
17
27
|
removeListener(event: ProviderEvent, listener: ProviderListener): void;
|
|
18
28
|
disconnect(): void;
|
|
29
|
+
/**
|
|
30
|
+
* The last security status reported by a wallet pop-up, or `undefined` when none arrived yet. A closed pop-up
|
|
31
|
+
* does not clear it.
|
|
32
|
+
*/
|
|
33
|
+
lastSecurityStatus(): WalletSecurityStatus | undefined;
|
|
19
34
|
}
|
|
20
35
|
/** Options for {@link createAsseteraWalletProvider}. */
|
|
21
36
|
interface AsseteraWalletProviderOptions {
|
|
22
|
-
/** Base URL of the wallet origin, e.g. `https://wallet.
|
|
37
|
+
/** Base URL of the wallet origin, e.g. `https://wallet.wallet-staging.assetera.com`. */
|
|
23
38
|
walletUrl: string;
|
|
24
39
|
/** Chain id used before the wallet reports one, and as the local `eth_chainId` fallback. */
|
|
25
40
|
defaultChainId: number;
|
|
26
41
|
/** `window.open` feature string. Defaults to `"popup,width=420,height=720"`. */
|
|
27
42
|
popupFeatures?: string;
|
|
43
|
+
/** Sign-in hint passed as `signIn`. Only a hint; the wallet may ignore it. */
|
|
44
|
+
signIn?: SignInHint;
|
|
28
45
|
}
|
|
29
46
|
/**
|
|
30
47
|
* EIP-1193 error carrying a JSON-RPC `code` (and optional `data`). This is what every rejected `request`
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
import { WalletSecurityStatus, SignInHint } from './protocol.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EIP-1193 provider for the Assetera Wallet pop-up — the opener side of the ADR-0054 D3/D4 protocol.
|
|
5
|
+
*
|
|
6
|
+
* The provider owns a single pop-up (`window.open(connectUrl(...), "assetera-wallet", ...)`) and speaks the
|
|
7
|
+
* wire format defined in `./protocol`. It never touches Dynamic, React, wagmi or viem, so a partner can use it
|
|
8
|
+
* on its own or through the wagmi / RainbowKit adapters in this package.
|
|
9
|
+
*/
|
|
10
|
+
|
|
1
11
|
/** Arguments accepted by `request`, mirroring EIP-1193. */
|
|
2
12
|
interface RequestArguments {
|
|
3
13
|
method: string;
|
|
4
14
|
params?: unknown[] | Record<string, unknown>;
|
|
5
15
|
}
|
|
6
|
-
/** EIP-1193 provider events emitted by the pop-up. */
|
|
7
|
-
type ProviderEvent = "accountsChanged" | "chainChanged" | "connect" | "disconnect";
|
|
16
|
+
/** EIP-1193 provider events emitted by the pop-up, plus the wallet security status. */
|
|
17
|
+
type ProviderEvent = "accountsChanged" | "chainChanged" | "connect" | "disconnect" | "assetera_security";
|
|
8
18
|
/**
|
|
9
19
|
* Listener shape for EIP-1193 provider events. `never[]` accepts a listener with any concrete parameter list
|
|
10
20
|
* (for example wagmi's `(accounts: string[]) => void`), while internal emission stays type-safe via a cast.
|
|
@@ -16,15 +26,22 @@ interface AsseteraWalletProvider {
|
|
|
16
26
|
on(event: ProviderEvent, listener: ProviderListener): void;
|
|
17
27
|
removeListener(event: ProviderEvent, listener: ProviderListener): void;
|
|
18
28
|
disconnect(): void;
|
|
29
|
+
/**
|
|
30
|
+
* The last security status reported by a wallet pop-up, or `undefined` when none arrived yet. A closed pop-up
|
|
31
|
+
* does not clear it.
|
|
32
|
+
*/
|
|
33
|
+
lastSecurityStatus(): WalletSecurityStatus | undefined;
|
|
19
34
|
}
|
|
20
35
|
/** Options for {@link createAsseteraWalletProvider}. */
|
|
21
36
|
interface AsseteraWalletProviderOptions {
|
|
22
|
-
/** Base URL of the wallet origin, e.g. `https://wallet.
|
|
37
|
+
/** Base URL of the wallet origin, e.g. `https://wallet.wallet-staging.assetera.com`. */
|
|
23
38
|
walletUrl: string;
|
|
24
39
|
/** Chain id used before the wallet reports one, and as the local `eth_chainId` fallback. */
|
|
25
40
|
defaultChainId: number;
|
|
26
41
|
/** `window.open` feature string. Defaults to `"popup,width=420,height=720"`. */
|
|
27
42
|
popupFeatures?: string;
|
|
43
|
+
/** Sign-in hint passed as `signIn`. Only a hint; the wallet may ignore it. */
|
|
44
|
+
signIn?: SignInHint;
|
|
28
45
|
}
|
|
29
46
|
/**
|
|
30
47
|
* EIP-1193 error carrying a JSON-RPC `code` (and optional `data`). This is what every rejected `request`
|
package/dist/rainbowkit.cjs
CHANGED
|
@@ -47,10 +47,26 @@ function isResponseMessage(value) {
|
|
|
47
47
|
function isEventMessage(value) {
|
|
48
48
|
return hasType(value, "event") && (value.event === "accountsChanged" || value.event === "chainChanged" || value.event === "disconnect");
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
var WALLET_PROTECTIONS = [
|
|
51
|
+
"unknown",
|
|
52
|
+
"add-factor",
|
|
53
|
+
"save-codes",
|
|
54
|
+
"create-codes",
|
|
55
|
+
"protected"
|
|
56
|
+
];
|
|
57
|
+
function isCount(value) {
|
|
58
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
59
|
+
}
|
|
60
|
+
function isSecurityMessage(value) {
|
|
61
|
+
if (!hasType(value, "security")) return false;
|
|
62
|
+
const data = value.data;
|
|
63
|
+
return isRecord(data) && typeof data.protection === "string" && WALLET_PROTECTIONS.includes(data.protection) && isCount(data.passkeys) && isCount(data.authenticatorApps);
|
|
64
|
+
}
|
|
65
|
+
function connectUrl(walletUrl, partnerOrigin, signIn) {
|
|
51
66
|
const url = new URL(CONNECT_PATH, walletUrl);
|
|
52
67
|
url.searchParams.set("origin", partnerOrigin);
|
|
53
68
|
url.searchParams.set("v", String(PROTOCOL_VERSION));
|
|
69
|
+
if (signIn !== void 0) url.searchParams.set("signIn", signIn);
|
|
54
70
|
return url.toString();
|
|
55
71
|
}
|
|
56
72
|
|
|
@@ -96,6 +112,7 @@ function createAsseteraWalletProvider(options) {
|
|
|
96
112
|
let accounts = [];
|
|
97
113
|
let chainIdHex = null;
|
|
98
114
|
let walletDisconnected = false;
|
|
115
|
+
let lastSecurity;
|
|
99
116
|
const pending = /* @__PURE__ */ new Map();
|
|
100
117
|
const listeners = /* @__PURE__ */ new Map();
|
|
101
118
|
let closeTimer = null;
|
|
@@ -170,7 +187,7 @@ function createAsseteraWalletProvider(options) {
|
|
|
170
187
|
}
|
|
171
188
|
if (typeof window === "undefined") return null;
|
|
172
189
|
const opened = window.open(
|
|
173
|
-
connectUrl(options.walletUrl, window.location.origin),
|
|
190
|
+
connectUrl(options.walletUrl, window.location.origin, options.signIn),
|
|
174
191
|
POPUP_NAME,
|
|
175
192
|
popupFeatures
|
|
176
193
|
);
|
|
@@ -221,6 +238,14 @@ function createAsseteraWalletProvider(options) {
|
|
|
221
238
|
walletDisconnected = true;
|
|
222
239
|
emit("disconnect", new ProviderRpcError(message.data.code, message.data.message, message.data.data));
|
|
223
240
|
}
|
|
241
|
+
function handleSecurityMessage(message) {
|
|
242
|
+
lastSecurity = {
|
|
243
|
+
protection: message.data.protection,
|
|
244
|
+
passkeys: message.data.passkeys,
|
|
245
|
+
authenticatorApps: message.data.authenticatorApps
|
|
246
|
+
};
|
|
247
|
+
emit("assetera_security", lastSecurity);
|
|
248
|
+
}
|
|
224
249
|
function onWindowMessage(event) {
|
|
225
250
|
if (event.origin !== walletOrigin) return;
|
|
226
251
|
if (popup === null || event.source !== popup) return;
|
|
@@ -233,6 +258,10 @@ function createAsseteraWalletProvider(options) {
|
|
|
233
258
|
handleResponse(data);
|
|
234
259
|
return;
|
|
235
260
|
}
|
|
261
|
+
if (isSecurityMessage(data)) {
|
|
262
|
+
handleSecurityMessage(data);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
236
265
|
if (isEventMessage(data)) handleEventMessage(data);
|
|
237
266
|
}
|
|
238
267
|
if (typeof window !== "undefined") window.addEventListener("message", onWindowMessage);
|
|
@@ -305,7 +334,10 @@ function createAsseteraWalletProvider(options) {
|
|
|
305
334
|
function removeListener(event, listener) {
|
|
306
335
|
removeEventListener(event, listener);
|
|
307
336
|
}
|
|
308
|
-
|
|
337
|
+
function lastSecurityStatus() {
|
|
338
|
+
return lastSecurity;
|
|
339
|
+
}
|
|
340
|
+
return { request, on, removeListener, disconnect, lastSecurityStatus };
|
|
309
341
|
}
|
|
310
342
|
|
|
311
343
|
// src/wagmi.ts
|
|
@@ -385,7 +417,8 @@ function asseteraWallet(parameters) {
|
|
|
385
417
|
if (!provider) {
|
|
386
418
|
provider = createAsseteraWalletProvider({
|
|
387
419
|
walletUrl: parameters.walletUrl,
|
|
388
|
-
defaultChainId: config.chains[0].id
|
|
420
|
+
defaultChainId: config.chains[0].id,
|
|
421
|
+
...parameters.signIn === void 0 ? {} : { signIn: parameters.signIn }
|
|
389
422
|
});
|
|
390
423
|
}
|
|
391
424
|
return provider;
|
|
@@ -435,7 +468,10 @@ function asseteraRainbowWallet(options) {
|
|
|
435
468
|
iconBackground: "#1a1a2e",
|
|
436
469
|
installed: true,
|
|
437
470
|
createConnector: (walletDetails) => core.createConnector((config) => ({
|
|
438
|
-
...asseteraWallet({
|
|
471
|
+
...asseteraWallet({
|
|
472
|
+
walletUrl: options.walletUrl,
|
|
473
|
+
...options.signIn === void 0 ? {} : { signIn: options.signIn }
|
|
474
|
+
})(config),
|
|
439
475
|
...walletDetails
|
|
440
476
|
}))
|
|
441
477
|
});
|