@metamask-previews/perps-controller 15.1.0-preview-00a181c → 15.1.0-preview-a302de5c3
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/CHANGELOG.md +0 -14
- package/dist/PerpsController-method-action-types.cjs.map +1 -1
- package/dist/PerpsController-method-action-types.d.cts +1 -20
- package/dist/PerpsController-method-action-types.d.cts.map +1 -1
- package/dist/PerpsController-method-action-types.d.mts +1 -20
- package/dist/PerpsController-method-action-types.d.mts.map +1 -1
- package/dist/PerpsController-method-action-types.mjs.map +1 -1
- package/dist/PerpsController.cjs +154 -65
- package/dist/PerpsController.cjs.map +1 -1
- package/dist/PerpsController.d.cts +43 -37
- package/dist/PerpsController.d.cts.map +1 -1
- package/dist/PerpsController.d.mts +43 -37
- package/dist/PerpsController.d.mts.map +1 -1
- package/dist/PerpsController.mjs +151 -64
- package/dist/PerpsController.mjs.map +1 -1
- package/dist/aggregation/SubscriptionMultiplexer.cjs +1 -1
- package/dist/aggregation/SubscriptionMultiplexer.cjs.map +1 -1
- package/dist/aggregation/SubscriptionMultiplexer.d.cts +1 -1
- package/dist/aggregation/SubscriptionMultiplexer.d.mts +1 -1
- package/dist/aggregation/SubscriptionMultiplexer.mjs +1 -1
- package/dist/aggregation/SubscriptionMultiplexer.mjs.map +1 -1
- package/dist/constants/index.cjs +1 -0
- package/dist/constants/index.cjs.map +1 -1
- package/dist/constants/index.d.cts +1 -0
- package/dist/constants/index.d.cts.map +1 -1
- package/dist/constants/index.d.mts +1 -0
- package/dist/constants/index.d.mts.map +1 -1
- package/dist/constants/index.mjs +1 -0
- package/dist/constants/index.mjs.map +1 -1
- package/dist/constants/myxConfig.cjs +253 -0
- package/dist/constants/myxConfig.cjs.map +1 -0
- package/dist/constants/myxConfig.d.cts +145 -0
- package/dist/constants/myxConfig.d.cts.map +1 -0
- package/dist/constants/myxConfig.d.mts +145 -0
- package/dist/constants/myxConfig.d.mts.map +1 -0
- package/dist/constants/myxConfig.mjs +243 -0
- package/dist/constants/myxConfig.mjs.map +1 -0
- package/dist/constants/perpsConfig.cjs +9 -4
- package/dist/constants/perpsConfig.cjs.map +1 -1
- package/dist/constants/perpsConfig.d.cts +5 -3
- package/dist/constants/perpsConfig.d.cts.map +1 -1
- package/dist/constants/perpsConfig.d.mts +5 -3
- package/dist/constants/perpsConfig.d.mts.map +1 -1
- package/dist/constants/perpsConfig.mjs +9 -4
- package/dist/constants/perpsConfig.mjs.map +1 -1
- package/dist/index.cjs +175 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.cjs +2 -8
- package/dist/providers/AggregatedPerpsProvider.cjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.cts +2 -3
- package/dist/providers/AggregatedPerpsProvider.d.cts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.mts +2 -3
- package/dist/providers/AggregatedPerpsProvider.d.mts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.mjs +2 -8
- package/dist/providers/AggregatedPerpsProvider.mjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.cjs +22 -118
- package/dist/providers/HyperLiquidProvider.cjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.cts +0 -31
- package/dist/providers/HyperLiquidProvider.d.cts.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.mts +0 -31
- package/dist/providers/HyperLiquidProvider.d.mts.map +1 -1
- package/dist/providers/HyperLiquidProvider.mjs +22 -118
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
- package/dist/providers/LighterProvider.cjs +1 -1
- package/dist/providers/LighterProvider.cjs.map +1 -1
- package/dist/providers/LighterProvider.mjs +1 -1
- package/dist/providers/LighterProvider.mjs.map +1 -1
- package/dist/routing/ProviderRouter.cjs +1 -1
- package/dist/routing/ProviderRouter.cjs.map +1 -1
- package/dist/routing/ProviderRouter.d.cts +1 -1
- package/dist/routing/ProviderRouter.d.mts +1 -1
- package/dist/routing/ProviderRouter.mjs +1 -1
- package/dist/routing/ProviderRouter.mjs.map +1 -1
- package/dist/services/HyperLiquidClientService.cjs.map +1 -1
- package/dist/services/HyperLiquidClientService.d.cts +16 -26
- package/dist/services/HyperLiquidClientService.d.cts.map +1 -1
- package/dist/services/HyperLiquidClientService.d.mts +16 -26
- package/dist/services/HyperLiquidClientService.d.mts.map +1 -1
- package/dist/services/HyperLiquidClientService.mjs.map +1 -1
- package/dist/services/HyperLiquidWalletService.cjs +30 -80
- package/dist/services/HyperLiquidWalletService.cjs.map +1 -1
- package/dist/services/HyperLiquidWalletService.d.cts +22 -48
- package/dist/services/HyperLiquidWalletService.d.cts.map +1 -1
- package/dist/services/HyperLiquidWalletService.d.mts +22 -48
- package/dist/services/HyperLiquidWalletService.d.mts.map +1 -1
- package/dist/services/HyperLiquidWalletService.mjs +30 -80
- package/dist/services/HyperLiquidWalletService.mjs.map +1 -1
- package/dist/services/LighterWalletService.cjs +1 -1
- package/dist/services/LighterWalletService.cjs.map +1 -1
- package/dist/services/LighterWalletService.d.cts +1 -1
- package/dist/services/LighterWalletService.d.mts +1 -1
- package/dist/services/LighterWalletService.mjs +1 -1
- package/dist/services/LighterWalletService.mjs.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +16 -10
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.mts +16 -10
- package/dist/types/index.d.mts.map +1 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/types/myx-types.cjs +41 -0
- package/dist/types/myx-types.cjs.map +1 -0
- package/dist/types/myx-types.d.cts +94 -0
- package/dist/types/myx-types.d.cts.map +1 -0
- package/dist/types/myx-types.d.mts +94 -0
- package/dist/types/myx-types.d.mts.map +1 -0
- package/dist/types/myx-types.mjs +26 -0
- package/dist/types/myx-types.mjs.map +1 -0
- package/dist/utils/lighterAdapter.cjs +2 -1
- package/dist/utils/lighterAdapter.cjs.map +1 -1
- package/dist/utils/lighterAdapter.d.cts +2 -1
- package/dist/utils/lighterAdapter.d.cts.map +1 -1
- package/dist/utils/lighterAdapter.d.mts +2 -1
- package/dist/utils/lighterAdapter.d.mts.map +1 -1
- package/dist/utils/lighterAdapter.mjs +2 -1
- package/dist/utils/lighterAdapter.mjs.map +1 -1
- package/dist/utils/myxAdapter.cjs +569 -0
- package/dist/utils/myxAdapter.cjs.map +1 -0
- package/dist/utils/myxAdapter.d.cts +168 -0
- package/dist/utils/myxAdapter.d.cts.map +1 -0
- package/dist/utils/myxAdapter.d.mts +168 -0
- package/dist/utils/myxAdapter.d.mts.map +1 -0
- package/dist/utils/myxAdapter.mjs +548 -0
- package/dist/utils/myxAdapter.mjs.map +1 -0
- package/package.json +8 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HyperLiquidWalletService.cjs","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n hasProperty,\n isValidHexAddress,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport type { CaipAccountId, Hex } from '@metamask/utils';\n\nimport { getChainId } from '../constants/hyperLiquidConfig.js';\nimport { PERPS_ERROR_CODES } from '../perpsErrorCodes.js';\nimport type {\n HyperLiquidSignTypedDataParams,\n HyperLiquidWalletParams,\n} from './HyperLiquidClientService.js';\nimport type {\n PerpsPlatformDependencies,\n PerpsTypedMessageParams,\n} from '../types/index.js';\nimport type { PerpsControllerMessengerBase } from '../types/messenger.js';\nimport {\n getSelectedEvmAccountDetailsFromMessenger,\n getSelectedEvmAccountFromMessenger,\n} from '../utils/accountUtils.js';\n\n// Mirrors KeyringTypes from @metamask/keyring-controller. Inlined to keep this\n// service portable between mobile and the core monorepo.\nconst HARDWARE_KEYRING_TYPES = new Set<string>([\n 'Ledger Hardware',\n 'Trezor Hardware',\n 'OneKey Hardware',\n 'Lattice Hardware',\n 'QR Hardware Wallet Device',\n]);\n\n/**\n * A local signer for a HyperLiquid agent account, in the SDK-native\n * `AbstractEthersV6Signer` shape (positional EIP-712 arguments, message as\n * the signed value). Provided by the client (e.g. a local key stored in\n * memory) so agent actions never touch the keyring.\n */\nexport type AgentSigner = {\n /** The agent account address used as the actor for signed actions. */\n address: `0x${string}`;\n /**\n * Sign EIP-712 typed data with the agent key (positional ethers-style\n * arguments; `types` must not include `EIP712Domain`).\n *\n * @param domain - The EIP-712 domain.\n * @param types - The EIP-712 type definitions (without `EIP712Domain`).\n * @param value - The message payload to sign.\n * @returns The hex signature.\n */\n signTypedData(\n domain: HyperLiquidSignTypedDataParams['domain'],\n types: HyperLiquidSignTypedDataParams['types'],\n value: Record<string, unknown>,\n ): Promise<string>;\n};\n\n/**\n * Service for MetaMask wallet integration with HyperLiquid SDK\n * Provides wallet adapter that implements AbstractWindowEthereum interface\n */\nexport class HyperLiquidWalletService {\n #isTestnet: boolean;\n\n // Platform dependencies for observability\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #messenger: PerpsControllerMessengerBase;\n\n constructor(\n deps: PerpsPlatformDependencies,\n messenger: PerpsControllerMessengerBase,\n options: { isTestnet?: boolean } = {},\n ) {\n this.#deps = deps;\n this.#messenger = messenger;\n this.#isTestnet = options.isTestnet ?? false;\n }\n\n /**\n * Check if the keyring is currently unlocked\n *\n * @returns True if the keyring is unlocked and available for signing.\n */\n public isKeyringUnlocked(): boolean {\n return this.#messenger.call('KeyringController:getState').isUnlocked;\n }\n\n /**\n * Check whether the selected EVM account is backed by hardware.\n *\n * @returns True for MetaMask hardware keyrings; false for software accounts.\n */\n public isSelectedHardwareWallet(): boolean {\n const selectedEvmAccount = getSelectedEvmAccountDetailsFromMessenger(\n this.#messenger,\n );\n if (!selectedEvmAccount || !hasProperty(selectedEvmAccount, 'metadata')) {\n return false;\n }\n\n const metadata = selectedEvmAccount.metadata as\n | { keyring?: { type?: string } }\n | undefined;\n const keyringType = metadata?.keyring?.type;\n\n return Boolean(keyringType && HARDWARE_KEYRING_TYPES.has(keyringType));\n }\n\n /**\n * Sign typed data via DI keyring controller\n *\n * @param msgParams - The typed message parameters including data and sender address.\n * @returns The signature string.\n */\n async #signTypedMessage(msgParams: PerpsTypedMessageParams): Promise<string> {\n if (!this.isKeyringUnlocked()) {\n throw new Error(PERPS_ERROR_CODES.KEYRING_LOCKED);\n }\n // Cast needed: PerpsTypedMessageParams uses loose `data: unknown` type\n // while KeyringController uses strict TypedMessageParams / SignTypedDataVersion\n return this.#messenger.call(\n 'KeyringController:signTypedMessage',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n msgParams as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'V4' as any,\n );\n }\n\n /**\n * Sign typed data with the master account via the keyring, resolving the\n * selected account fresh so account switches cannot race the adapter.\n *\n * @param params - The typed-data signing request the SDK passed to the adapter.\n * @returns The signature string.\n */\n async #signWithMaster(params: HyperLiquidSignTypedDataParams): Promise<Hex> {\n const currentEvmAccount = getSelectedEvmAccountFromMessenger(\n this.#messenger,\n );\n\n if (!currentEvmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const currentAddress = currentEvmAccount.address as Hex;\n\n this.#deps.debugLogger.log(\n 'HyperLiquidWalletService: Signing typed data (master fallback)',\n {\n address: currentAddress,\n primaryType: params.primaryType,\n domain: params.domain,\n },\n );\n\n const signature = await this.#signTypedMessage({\n from: currentAddress,\n data: {\n domain: params.domain,\n types: params.types,\n primaryType: params.primaryType,\n message: params.message,\n },\n });\n\n return signature as Hex;\n }\n\n /**\n * Whether a typed-data signing request is an L1 (phantom-agent) action.\n *\n * The HyperLiquid SDK signs L1 actions (order/cancel/modify/TWAP/leverage/\n * margin/agentSetAbstraction) with EIP-712 primaryType `Agent` over domain\n * `{ name: \"Exchange\", version: \"1\", chainId: 1337 }`. Only these may be\n * signed by an agent key; every other shape (e.g. `approveBuilderFee`,\n * `userSetAbstraction`, `sendAsset`, `withdraw3` over the\n * `HyperliquidSignTransaction` domain) is a user-signed action that\n * authorizes the master account and must be signed by the master wallet.\n *\n * @param primaryType - The EIP-712 primary type of the signing request.\n * @param domainName - The EIP-712 domain name of the signing request.\n * @returns True when the request belongs to the agent-signable L1 class.\n */\n #isL1AgentAction(primaryType: string, domainName?: string): boolean {\n return primaryType === 'Agent' || domainName === 'Exchange';\n }\n\n /**\n * Create a wallet adapter backed by a local agent signer.\n *\n * The returned adapter keeps the params-style `signTypedData` shape the SDK\n * already accepts (viem local account), but routes by typed-data shape:\n * L1 (phantom-agent) actions — primaryType `Agent` over the `Exchange`\n * domain — are signed directly by the injected local signer with no keyring\n * contact; user-signed actions (`approveBuilderFee`, `userSetAbstraction`,\n * `sendAsset`, `withdraw3`, … over the `HyperliquidSignTransaction` domain)\n * are master-account authorizations and fall through to the master keyring\n * signing path, so hardware users get the normal device prompt. The SDK's\n * viem adapters inject an `EIP712Domain` entry into `types` before calling\n * params-style wallets; ethers-style signers reject that entry, so it is\n * stripped before delegating to the agent signer (the master path passes\n * `types` through unchanged, matching the pre-seam master adapter).\n *\n * @param agentSigner - The local agent signer to delegate L1 actions to.\n * @returns The agent wallet adapter.\n */\n public createAgentWalletAdapter(\n agentSigner: AgentSigner,\n ): HyperLiquidWalletParams {\n return {\n // The agent address is returned for identity purposes: the SDK only uses\n // it for local lock/nonce keying (`getWalletAddress`), never inside the\n // signed payload — HyperLiquid recovers the signer from the signature.\n address: agentSigner.address,\n signTypedData: async (\n params: HyperLiquidSignTypedDataParams,\n ): Promise<Hex> => {\n if (this.#isL1AgentAction(params.primaryType, params.domain?.name)) {\n const { EIP712Domain: _eip712Domain, ...types } = params.types;\n\n this.#deps.debugLogger.log(\n 'HyperLiquidWalletService: Signing typed data (agent mode)',\n {\n address: agentSigner.address,\n primaryType: params.primaryType,\n },\n );\n\n return (await agentSigner.signTypedData(\n params.domain,\n types,\n params.message,\n )) as Hex;\n }\n\n // User-signed action: master-account authorization, must be signed\n // by the master wallet (device prompt on hardware).\n return this.#signWithMaster(params);\n },\n getChainId: async (): Promise<number> =>\n parseInt(getChainId(this.#isTestnet), 10),\n };\n }\n\n /**\n * Create the master-keyring wallet adapter for the HyperLiquid SDK.\n *\n * This factory is synchronous and always signs via the selected master\n * account. Agent wallets are built separately with\n * {@link createAgentWalletAdapter}; the provider selects which adapter the\n * SDK clients use.\n *\n * @returns The wallet adapter with address, signTypedData, and getChainId methods.\n */\n public createWalletAdapter(): HyperLiquidWalletParams {\n // Get current EVM account via DI messenger\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const address = evmAccount.address as Hex;\n\n return {\n address,\n signTypedData: async (\n params: HyperLiquidSignTypedDataParams,\n ): Promise<Hex> => this.#signWithMaster(params),\n getChainId: async (): Promise<number> =>\n parseInt(getChainId(this.#isTestnet), 10),\n };\n }\n\n /**\n * Get current account ID using messenger\n *\n * @returns The CAIP account ID for the current EVM account.\n */\n public async getCurrentAccountId(): Promise<CaipAccountId> {\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const chainId = getChainId(this.#isTestnet);\n const caipAccountId: CaipAccountId = `eip155:${chainId}:${evmAccount.address}`;\n\n return caipAccountId;\n }\n\n /**\n * Get validated user address as Hex from account ID\n *\n * @param accountId - The CAIP account ID to extract the address from.\n * @returns The validated hex address.\n */\n public getUserAddress(accountId: CaipAccountId): Hex {\n const parsed = parseCaipAccountId(accountId);\n const address = parsed.address as Hex;\n\n if (!isValidHexAddress(address)) {\n throw new Error(PERPS_ERROR_CODES.INVALID_ADDRESS_FORMAT);\n }\n\n return address;\n }\n\n /**\n * Get user address with default fallback to current account\n *\n * @param accountId - Optional CAIP account ID; defaults to current account if omitted.\n * @returns The validated hex address.\n */\n public async getUserAddressWithDefault(\n accountId?: CaipAccountId,\n ): Promise<Hex> {\n const id = accountId ?? (await this.getCurrentAccountId());\n return this.getUserAddress(id);\n }\n\n /**\n * Update testnet mode\n *\n * @param isTestnet - Whether to enable testnet mode.\n */\n public setTestnetMode(isTestnet: boolean): void {\n this.#isTestnet = isTestnet;\n }\n\n /**\n * Check if running on testnet\n *\n * @returns True if the service is in testnet mode.\n */\n public isTestnetMode(): boolean {\n return this.#isTestnet;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"HyperLiquidWalletService.cjs","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n hasProperty,\n isValidHexAddress,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport type { CaipAccountId, Hex } from '@metamask/utils';\n\nimport { getChainId } from '../constants/hyperLiquidConfig.js';\nimport { PERPS_ERROR_CODES } from '../perpsErrorCodes.js';\nimport type {\n PerpsPlatformDependencies,\n PerpsTypedMessageParams,\n} from '../types/index.js';\nimport type { PerpsControllerMessengerBase } from '../types/messenger.js';\nimport {\n getSelectedEvmAccountDetailsFromMessenger,\n getSelectedEvmAccountFromMessenger,\n} from '../utils/accountUtils.js';\n\n// Mirrors KeyringTypes from @metamask/keyring-controller. Inlined to keep this\n// service portable between mobile and the core monorepo.\nconst HARDWARE_KEYRING_TYPES = new Set<string>([\n 'Ledger Hardware',\n 'Trezor Hardware',\n 'OneKey Hardware',\n 'Lattice Hardware',\n 'QR Hardware Wallet Device',\n]);\n\n/**\n * Service for MetaMask wallet integration with HyperLiquid SDK\n * Provides wallet adapter that implements AbstractWindowEthereum interface\n */\nexport class HyperLiquidWalletService {\n #isTestnet: boolean;\n\n // Platform dependencies for observability\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #messenger: PerpsControllerMessengerBase;\n\n constructor(\n deps: PerpsPlatformDependencies,\n messenger: PerpsControllerMessengerBase,\n options: { isTestnet?: boolean } = {},\n ) {\n this.#deps = deps;\n this.#messenger = messenger;\n this.#isTestnet = options.isTestnet ?? false;\n }\n\n /**\n * Check if the keyring is currently unlocked\n *\n * @returns True if the keyring is unlocked and available for signing.\n */\n public isKeyringUnlocked(): boolean {\n return this.#messenger.call('KeyringController:getState').isUnlocked;\n }\n\n /**\n * Check whether the selected EVM account is backed by hardware.\n *\n * @returns True for MetaMask hardware keyrings; false for software accounts.\n */\n public isSelectedHardwareWallet(): boolean {\n const selectedEvmAccount = getSelectedEvmAccountDetailsFromMessenger(\n this.#messenger,\n );\n if (!selectedEvmAccount || !hasProperty(selectedEvmAccount, 'metadata')) {\n return false;\n }\n\n const metadata = selectedEvmAccount.metadata as\n | { keyring?: { type?: string } }\n | undefined;\n const keyringType = metadata?.keyring?.type;\n\n return Boolean(keyringType && HARDWARE_KEYRING_TYPES.has(keyringType));\n }\n\n /**\n * Sign typed data via DI keyring controller\n *\n * @param msgParams - The typed message parameters including data and sender address.\n * @returns The signature string.\n */\n async #signTypedMessage(msgParams: PerpsTypedMessageParams): Promise<string> {\n if (!this.isKeyringUnlocked()) {\n throw new Error(PERPS_ERROR_CODES.KEYRING_LOCKED);\n }\n // Cast needed: PerpsTypedMessageParams uses loose `data: unknown` type\n // while KeyringController uses strict TypedMessageParams / SignTypedDataVersion\n return this.#messenger.call(\n 'KeyringController:signTypedMessage',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n msgParams as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'V4' as any,\n );\n }\n\n /**\n * Create wallet adapter that implements AbstractViemJsonRpcAccount interface\n * Required by @nktkas/hyperliquid SDK for signing transactions\n *\n * @returns The wallet adapter with address, signTypedData, and getChainId methods.\n */\n public createWalletAdapter(): {\n address: Hex;\n signTypedData: (params: {\n domain: {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: Hex;\n };\n types: {\n [key: string]: { name: string; type: string }[];\n };\n primaryType: string;\n message: Record<string, unknown>;\n }) => Promise<Hex>;\n getChainId?: () => Promise<number>;\n } {\n // Get current EVM account via DI messenger\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const address = evmAccount.address as Hex;\n\n return {\n address,\n signTypedData: async (params: {\n domain: {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: Hex;\n };\n types: {\n [key: string]: { name: string; type: string }[];\n };\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<Hex> => {\n // Get FRESH account on every sign to handle account switches\n // This prevents race conditions where wallet adapter was created with old account\n const currentEvmAccount = getSelectedEvmAccountFromMessenger(\n this.#messenger,\n );\n\n if (!currentEvmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const currentAddress = currentEvmAccount.address as Hex;\n\n // Construct EIP-712 typed data\n const typedData = {\n domain: params.domain,\n types: params.types,\n primaryType: params.primaryType,\n message: params.message,\n };\n\n this.#deps.debugLogger.log(\n 'HyperLiquidWalletService: Signing typed data',\n {\n address: currentAddress,\n primaryType: params.primaryType,\n domain: params.domain,\n },\n );\n\n // Use messenger to sign typed data\n const signature = await this.#signTypedMessage({\n from: currentAddress,\n data: typedData,\n });\n\n return signature as Hex;\n },\n getChainId: async (): Promise<number> =>\n parseInt(getChainId(this.#isTestnet), 10),\n };\n }\n\n /**\n * Get current account ID using messenger\n *\n * @returns The CAIP account ID for the current EVM account.\n */\n public async getCurrentAccountId(): Promise<CaipAccountId> {\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const chainId = getChainId(this.#isTestnet);\n const caipAccountId: CaipAccountId = `eip155:${chainId}:${evmAccount.address}`;\n\n return caipAccountId;\n }\n\n /**\n * Get validated user address as Hex from account ID\n *\n * @param accountId - The CAIP account ID to extract the address from.\n * @returns The validated hex address.\n */\n public getUserAddress(accountId: CaipAccountId): Hex {\n const parsed = parseCaipAccountId(accountId);\n const address = parsed.address as Hex;\n\n if (!isValidHexAddress(address)) {\n throw new Error(PERPS_ERROR_CODES.INVALID_ADDRESS_FORMAT);\n }\n\n return address;\n }\n\n /**\n * Get user address with default fallback to current account\n *\n * @param accountId - Optional CAIP account ID; defaults to current account if omitted.\n * @returns The validated hex address.\n */\n public async getUserAddressWithDefault(\n accountId?: CaipAccountId,\n ): Promise<Hex> {\n const id = accountId ?? (await this.getCurrentAccountId());\n return this.getUserAddress(id);\n }\n\n /**\n * Update testnet mode\n *\n * @param isTestnet - Whether to enable testnet mode.\n */\n public setTestnetMode(isTestnet: boolean): void {\n this.#isTestnet = isTestnet;\n }\n\n /**\n * Check if running on testnet\n *\n * @returns True if the service is in testnet mode.\n */\n public isTestnetMode(): boolean {\n return this.#isTestnet;\n }\n}\n"]}
|
|
@@ -1,27 +1,6 @@
|
|
|
1
1
|
import type { CaipAccountId, Hex } from "@metamask/utils";
|
|
2
|
-
import type { HyperLiquidSignTypedDataParams, HyperLiquidWalletParams } from "./HyperLiquidClientService.cjs";
|
|
3
2
|
import type { PerpsPlatformDependencies } from "../types/index.cjs";
|
|
4
3
|
import type { PerpsControllerMessengerBase } from "../types/messenger.cjs";
|
|
5
|
-
/**
|
|
6
|
-
* A local signer for a HyperLiquid agent account, in the SDK-native
|
|
7
|
-
* `AbstractEthersV6Signer` shape (positional EIP-712 arguments, message as
|
|
8
|
-
* the signed value). Provided by the client (e.g. a local key stored in
|
|
9
|
-
* memory) so agent actions never touch the keyring.
|
|
10
|
-
*/
|
|
11
|
-
export type AgentSigner = {
|
|
12
|
-
/** The agent account address used as the actor for signed actions. */
|
|
13
|
-
address: `0x${string}`;
|
|
14
|
-
/**
|
|
15
|
-
* Sign EIP-712 typed data with the agent key (positional ethers-style
|
|
16
|
-
* arguments; `types` must not include `EIP712Domain`).
|
|
17
|
-
*
|
|
18
|
-
* @param domain - The EIP-712 domain.
|
|
19
|
-
* @param types - The EIP-712 type definitions (without `EIP712Domain`).
|
|
20
|
-
* @param value - The message payload to sign.
|
|
21
|
-
* @returns The hex signature.
|
|
22
|
-
*/
|
|
23
|
-
signTypedData(domain: HyperLiquidSignTypedDataParams['domain'], types: HyperLiquidSignTypedDataParams['types'], value: Record<string, unknown>): Promise<string>;
|
|
24
|
-
};
|
|
25
4
|
/**
|
|
26
5
|
* Service for MetaMask wallet integration with HyperLiquid SDK
|
|
27
6
|
* Provides wallet adapter that implements AbstractWindowEthereum interface
|
|
@@ -44,36 +23,31 @@ export declare class HyperLiquidWalletService {
|
|
|
44
23
|
*/
|
|
45
24
|
isSelectedHardwareWallet(): boolean;
|
|
46
25
|
/**
|
|
47
|
-
* Create
|
|
48
|
-
*
|
|
49
|
-
* The returned adapter keeps the params-style `signTypedData` shape the SDK
|
|
50
|
-
* already accepts (viem local account), but routes by typed-data shape:
|
|
51
|
-
* L1 (phantom-agent) actions — primaryType `Agent` over the `Exchange`
|
|
52
|
-
* domain — are signed directly by the injected local signer with no keyring
|
|
53
|
-
* contact; user-signed actions (`approveBuilderFee`, `userSetAbstraction`,
|
|
54
|
-
* `sendAsset`, `withdraw3`, … over the `HyperliquidSignTransaction` domain)
|
|
55
|
-
* are master-account authorizations and fall through to the master keyring
|
|
56
|
-
* signing path, so hardware users get the normal device prompt. The SDK's
|
|
57
|
-
* viem adapters inject an `EIP712Domain` entry into `types` before calling
|
|
58
|
-
* params-style wallets; ethers-style signers reject that entry, so it is
|
|
59
|
-
* stripped before delegating to the agent signer (the master path passes
|
|
60
|
-
* `types` through unchanged, matching the pre-seam master adapter).
|
|
61
|
-
*
|
|
62
|
-
* @param agentSigner - The local agent signer to delegate L1 actions to.
|
|
63
|
-
* @returns The agent wallet adapter.
|
|
64
|
-
*/
|
|
65
|
-
createAgentWalletAdapter(agentSigner: AgentSigner): HyperLiquidWalletParams;
|
|
66
|
-
/**
|
|
67
|
-
* Create the master-keyring wallet adapter for the HyperLiquid SDK.
|
|
68
|
-
*
|
|
69
|
-
* This factory is synchronous and always signs via the selected master
|
|
70
|
-
* account. Agent wallets are built separately with
|
|
71
|
-
* {@link createAgentWalletAdapter}; the provider selects which adapter the
|
|
72
|
-
* SDK clients use.
|
|
26
|
+
* Create wallet adapter that implements AbstractViemJsonRpcAccount interface
|
|
27
|
+
* Required by @nktkas/hyperliquid SDK for signing transactions
|
|
73
28
|
*
|
|
74
29
|
* @returns The wallet adapter with address, signTypedData, and getChainId methods.
|
|
75
30
|
*/
|
|
76
|
-
createWalletAdapter():
|
|
31
|
+
createWalletAdapter(): {
|
|
32
|
+
address: Hex;
|
|
33
|
+
signTypedData: (params: {
|
|
34
|
+
domain: {
|
|
35
|
+
name: string;
|
|
36
|
+
version: string;
|
|
37
|
+
chainId: number;
|
|
38
|
+
verifyingContract: Hex;
|
|
39
|
+
};
|
|
40
|
+
types: {
|
|
41
|
+
[key: string]: {
|
|
42
|
+
name: string;
|
|
43
|
+
type: string;
|
|
44
|
+
}[];
|
|
45
|
+
};
|
|
46
|
+
primaryType: string;
|
|
47
|
+
message: Record<string, unknown>;
|
|
48
|
+
}) => Promise<Hex>;
|
|
49
|
+
getChainId?: () => Promise<number>;
|
|
50
|
+
};
|
|
77
51
|
/**
|
|
78
52
|
* Get current account ID using messenger
|
|
79
53
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HyperLiquidWalletService.d.cts","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,wBAAwB;AAI1D,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"HyperLiquidWalletService.d.cts","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,wBAAwB;AAI1D,OAAO,KAAK,EACV,yBAAyB,EAE1B,2BAA0B;AAC3B,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAA8B;AAgB1E;;;GAGG;AACH,qBAAa,wBAAwB;;gBASjC,IAAI,EAAE,yBAAyB,EAC/B,SAAS,EAAE,4BAA4B,EACvC,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO;IAOvC;;;;OAIG;IACI,iBAAiB,IAAI,OAAO;IAInC;;;;OAIG;IACI,wBAAwB,IAAI,OAAO;IAqC1C;;;;;OAKG;IACI,mBAAmB,IAAI;QAC5B,OAAO,EAAE,GAAG,CAAC;QACb,aAAa,EAAE,CAAC,MAAM,EAAE;YACtB,MAAM,EAAE;gBACN,IAAI,EAAE,MAAM,CAAC;gBACb,OAAO,EAAE,MAAM,CAAC;gBAChB,OAAO,EAAE,MAAM,CAAC;gBAChB,iBAAiB,EAAE,GAAG,CAAC;aACxB,CAAC;YACF,KAAK,EAAE;gBACL,CAAC,GAAG,EAAE,MAAM,GAAG;oBAAE,IAAI,EAAE,MAAM,CAAC;oBAAC,IAAI,EAAE,MAAM,CAAA;iBAAE,EAAE,CAAC;aACjD,CAAC;YACF,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SAClC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;KACpC;IAmED;;;;OAIG;IACU,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC;IAa1D;;;;;OAKG;IACI,cAAc,CAAC,SAAS,EAAE,aAAa,GAAG,GAAG;IAWpD;;;;;OAKG;IACU,yBAAyB,CACpC,SAAS,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,GAAG,CAAC;IAKf;;;;OAIG;IACI,cAAc,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAI/C;;;;OAIG;IACI,aAAa,IAAI,OAAO;CAGhC"}
|
|
@@ -1,27 +1,6 @@
|
|
|
1
1
|
import type { CaipAccountId, Hex } from "@metamask/utils";
|
|
2
|
-
import type { HyperLiquidSignTypedDataParams, HyperLiquidWalletParams } from "./HyperLiquidClientService.mjs";
|
|
3
2
|
import type { PerpsPlatformDependencies } from "../types/index.mjs";
|
|
4
3
|
import type { PerpsControllerMessengerBase } from "../types/messenger.mjs";
|
|
5
|
-
/**
|
|
6
|
-
* A local signer for a HyperLiquid agent account, in the SDK-native
|
|
7
|
-
* `AbstractEthersV6Signer` shape (positional EIP-712 arguments, message as
|
|
8
|
-
* the signed value). Provided by the client (e.g. a local key stored in
|
|
9
|
-
* memory) so agent actions never touch the keyring.
|
|
10
|
-
*/
|
|
11
|
-
export type AgentSigner = {
|
|
12
|
-
/** The agent account address used as the actor for signed actions. */
|
|
13
|
-
address: `0x${string}`;
|
|
14
|
-
/**
|
|
15
|
-
* Sign EIP-712 typed data with the agent key (positional ethers-style
|
|
16
|
-
* arguments; `types` must not include `EIP712Domain`).
|
|
17
|
-
*
|
|
18
|
-
* @param domain - The EIP-712 domain.
|
|
19
|
-
* @param types - The EIP-712 type definitions (without `EIP712Domain`).
|
|
20
|
-
* @param value - The message payload to sign.
|
|
21
|
-
* @returns The hex signature.
|
|
22
|
-
*/
|
|
23
|
-
signTypedData(domain: HyperLiquidSignTypedDataParams['domain'], types: HyperLiquidSignTypedDataParams['types'], value: Record<string, unknown>): Promise<string>;
|
|
24
|
-
};
|
|
25
4
|
/**
|
|
26
5
|
* Service for MetaMask wallet integration with HyperLiquid SDK
|
|
27
6
|
* Provides wallet adapter that implements AbstractWindowEthereum interface
|
|
@@ -44,36 +23,31 @@ export declare class HyperLiquidWalletService {
|
|
|
44
23
|
*/
|
|
45
24
|
isSelectedHardwareWallet(): boolean;
|
|
46
25
|
/**
|
|
47
|
-
* Create
|
|
48
|
-
*
|
|
49
|
-
* The returned adapter keeps the params-style `signTypedData` shape the SDK
|
|
50
|
-
* already accepts (viem local account), but routes by typed-data shape:
|
|
51
|
-
* L1 (phantom-agent) actions — primaryType `Agent` over the `Exchange`
|
|
52
|
-
* domain — are signed directly by the injected local signer with no keyring
|
|
53
|
-
* contact; user-signed actions (`approveBuilderFee`, `userSetAbstraction`,
|
|
54
|
-
* `sendAsset`, `withdraw3`, … over the `HyperliquidSignTransaction` domain)
|
|
55
|
-
* are master-account authorizations and fall through to the master keyring
|
|
56
|
-
* signing path, so hardware users get the normal device prompt. The SDK's
|
|
57
|
-
* viem adapters inject an `EIP712Domain` entry into `types` before calling
|
|
58
|
-
* params-style wallets; ethers-style signers reject that entry, so it is
|
|
59
|
-
* stripped before delegating to the agent signer (the master path passes
|
|
60
|
-
* `types` through unchanged, matching the pre-seam master adapter).
|
|
61
|
-
*
|
|
62
|
-
* @param agentSigner - The local agent signer to delegate L1 actions to.
|
|
63
|
-
* @returns The agent wallet adapter.
|
|
64
|
-
*/
|
|
65
|
-
createAgentWalletAdapter(agentSigner: AgentSigner): HyperLiquidWalletParams;
|
|
66
|
-
/**
|
|
67
|
-
* Create the master-keyring wallet adapter for the HyperLiquid SDK.
|
|
68
|
-
*
|
|
69
|
-
* This factory is synchronous and always signs via the selected master
|
|
70
|
-
* account. Agent wallets are built separately with
|
|
71
|
-
* {@link createAgentWalletAdapter}; the provider selects which adapter the
|
|
72
|
-
* SDK clients use.
|
|
26
|
+
* Create wallet adapter that implements AbstractViemJsonRpcAccount interface
|
|
27
|
+
* Required by @nktkas/hyperliquid SDK for signing transactions
|
|
73
28
|
*
|
|
74
29
|
* @returns The wallet adapter with address, signTypedData, and getChainId methods.
|
|
75
30
|
*/
|
|
76
|
-
createWalletAdapter():
|
|
31
|
+
createWalletAdapter(): {
|
|
32
|
+
address: Hex;
|
|
33
|
+
signTypedData: (params: {
|
|
34
|
+
domain: {
|
|
35
|
+
name: string;
|
|
36
|
+
version: string;
|
|
37
|
+
chainId: number;
|
|
38
|
+
verifyingContract: Hex;
|
|
39
|
+
};
|
|
40
|
+
types: {
|
|
41
|
+
[key: string]: {
|
|
42
|
+
name: string;
|
|
43
|
+
type: string;
|
|
44
|
+
}[];
|
|
45
|
+
};
|
|
46
|
+
primaryType: string;
|
|
47
|
+
message: Record<string, unknown>;
|
|
48
|
+
}) => Promise<Hex>;
|
|
49
|
+
getChainId?: () => Promise<number>;
|
|
50
|
+
};
|
|
77
51
|
/**
|
|
78
52
|
* Get current account ID using messenger
|
|
79
53
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HyperLiquidWalletService.d.mts","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,wBAAwB;AAI1D,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"HyperLiquidWalletService.d.mts","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,wBAAwB;AAI1D,OAAO,KAAK,EACV,yBAAyB,EAE1B,2BAA0B;AAC3B,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAA8B;AAgB1E;;;GAGG;AACH,qBAAa,wBAAwB;;gBASjC,IAAI,EAAE,yBAAyB,EAC/B,SAAS,EAAE,4BAA4B,EACvC,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO;IAOvC;;;;OAIG;IACI,iBAAiB,IAAI,OAAO;IAInC;;;;OAIG;IACI,wBAAwB,IAAI,OAAO;IAqC1C;;;;;OAKG;IACI,mBAAmB,IAAI;QAC5B,OAAO,EAAE,GAAG,CAAC;QACb,aAAa,EAAE,CAAC,MAAM,EAAE;YACtB,MAAM,EAAE;gBACN,IAAI,EAAE,MAAM,CAAC;gBACb,OAAO,EAAE,MAAM,CAAC;gBAChB,OAAO,EAAE,MAAM,CAAC;gBAChB,iBAAiB,EAAE,GAAG,CAAC;aACxB,CAAC;YACF,KAAK,EAAE;gBACL,CAAC,GAAG,EAAE,MAAM,GAAG;oBAAE,IAAI,EAAE,MAAM,CAAC;oBAAC,IAAI,EAAE,MAAM,CAAA;iBAAE,EAAE,CAAC;aACjD,CAAC;YACF,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SAClC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;KACpC;IAmED;;;;OAIG;IACU,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC;IAa1D;;;;;OAKG;IACI,cAAc,CAAC,SAAS,EAAE,aAAa,GAAG,GAAG;IAWpD;;;;;OAKG;IACU,yBAAyB,CACpC,SAAS,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,GAAG,CAAC;IAKf;;;;OAIG;IACI,cAAc,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAI/C;;;;OAIG;IACI,aAAa,IAAI,OAAO;CAGhC"}
|
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _HyperLiquidWalletService_instances, _HyperLiquidWalletService_isTestnet, _HyperLiquidWalletService_deps, _HyperLiquidWalletService_messenger, _HyperLiquidWalletService_signTypedMessage
|
|
12
|
+
var _HyperLiquidWalletService_instances, _HyperLiquidWalletService_isTestnet, _HyperLiquidWalletService_deps, _HyperLiquidWalletService_messenger, _HyperLiquidWalletService_signTypedMessage;
|
|
13
13
|
import { hasProperty, isValidHexAddress, parseCaipAccountId } from "@metamask/utils";
|
|
14
14
|
import { getChainId } from "../constants/hyperLiquidConfig.mjs";
|
|
15
15
|
import { PERPS_ERROR_CODES } from "../perpsErrorCodes.mjs";
|
|
@@ -61,53 +61,8 @@ export class HyperLiquidWalletService {
|
|
|
61
61
|
return Boolean(keyringType && HARDWARE_KEYRING_TYPES.has(keyringType));
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
|
-
* Create
|
|
65
|
-
*
|
|
66
|
-
* The returned adapter keeps the params-style `signTypedData` shape the SDK
|
|
67
|
-
* already accepts (viem local account), but routes by typed-data shape:
|
|
68
|
-
* L1 (phantom-agent) actions — primaryType `Agent` over the `Exchange`
|
|
69
|
-
* domain — are signed directly by the injected local signer with no keyring
|
|
70
|
-
* contact; user-signed actions (`approveBuilderFee`, `userSetAbstraction`,
|
|
71
|
-
* `sendAsset`, `withdraw3`, … over the `HyperliquidSignTransaction` domain)
|
|
72
|
-
* are master-account authorizations and fall through to the master keyring
|
|
73
|
-
* signing path, so hardware users get the normal device prompt. The SDK's
|
|
74
|
-
* viem adapters inject an `EIP712Domain` entry into `types` before calling
|
|
75
|
-
* params-style wallets; ethers-style signers reject that entry, so it is
|
|
76
|
-
* stripped before delegating to the agent signer (the master path passes
|
|
77
|
-
* `types` through unchanged, matching the pre-seam master adapter).
|
|
78
|
-
*
|
|
79
|
-
* @param agentSigner - The local agent signer to delegate L1 actions to.
|
|
80
|
-
* @returns The agent wallet adapter.
|
|
81
|
-
*/
|
|
82
|
-
createAgentWalletAdapter(agentSigner) {
|
|
83
|
-
return {
|
|
84
|
-
// The agent address is returned for identity purposes: the SDK only uses
|
|
85
|
-
// it for local lock/nonce keying (`getWalletAddress`), never inside the
|
|
86
|
-
// signed payload — HyperLiquid recovers the signer from the signature.
|
|
87
|
-
address: agentSigner.address,
|
|
88
|
-
signTypedData: async (params) => {
|
|
89
|
-
if (__classPrivateFieldGet(this, _HyperLiquidWalletService_instances, "m", _HyperLiquidWalletService_isL1AgentAction).call(this, params.primaryType, params.domain?.name)) {
|
|
90
|
-
const { EIP712Domain: _eip712Domain, ...types } = params.types;
|
|
91
|
-
__classPrivateFieldGet(this, _HyperLiquidWalletService_deps, "f").debugLogger.log('HyperLiquidWalletService: Signing typed data (agent mode)', {
|
|
92
|
-
address: agentSigner.address,
|
|
93
|
-
primaryType: params.primaryType,
|
|
94
|
-
});
|
|
95
|
-
return (await agentSigner.signTypedData(params.domain, types, params.message));
|
|
96
|
-
}
|
|
97
|
-
// User-signed action: master-account authorization, must be signed
|
|
98
|
-
// by the master wallet (device prompt on hardware).
|
|
99
|
-
return __classPrivateFieldGet(this, _HyperLiquidWalletService_instances, "m", _HyperLiquidWalletService_signWithMaster).call(this, params);
|
|
100
|
-
},
|
|
101
|
-
getChainId: async () => parseInt(getChainId(__classPrivateFieldGet(this, _HyperLiquidWalletService_isTestnet, "f")), 10),
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Create the master-keyring wallet adapter for the HyperLiquid SDK.
|
|
106
|
-
*
|
|
107
|
-
* This factory is synchronous and always signs via the selected master
|
|
108
|
-
* account. Agent wallets are built separately with
|
|
109
|
-
* {@link createAgentWalletAdapter}; the provider selects which adapter the
|
|
110
|
-
* SDK clients use.
|
|
64
|
+
* Create wallet adapter that implements AbstractViemJsonRpcAccount interface
|
|
65
|
+
* Required by @nktkas/hyperliquid SDK for signing transactions
|
|
111
66
|
*
|
|
112
67
|
* @returns The wallet adapter with address, signTypedData, and getChainId methods.
|
|
113
68
|
*/
|
|
@@ -120,7 +75,33 @@ export class HyperLiquidWalletService {
|
|
|
120
75
|
const address = evmAccount.address;
|
|
121
76
|
return {
|
|
122
77
|
address,
|
|
123
|
-
signTypedData: async (params) =>
|
|
78
|
+
signTypedData: async (params) => {
|
|
79
|
+
// Get FRESH account on every sign to handle account switches
|
|
80
|
+
// This prevents race conditions where wallet adapter was created with old account
|
|
81
|
+
const currentEvmAccount = getSelectedEvmAccountFromMessenger(__classPrivateFieldGet(this, _HyperLiquidWalletService_messenger, "f"));
|
|
82
|
+
if (!currentEvmAccount?.address) {
|
|
83
|
+
throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);
|
|
84
|
+
}
|
|
85
|
+
const currentAddress = currentEvmAccount.address;
|
|
86
|
+
// Construct EIP-712 typed data
|
|
87
|
+
const typedData = {
|
|
88
|
+
domain: params.domain,
|
|
89
|
+
types: params.types,
|
|
90
|
+
primaryType: params.primaryType,
|
|
91
|
+
message: params.message,
|
|
92
|
+
};
|
|
93
|
+
__classPrivateFieldGet(this, _HyperLiquidWalletService_deps, "f").debugLogger.log('HyperLiquidWalletService: Signing typed data', {
|
|
94
|
+
address: currentAddress,
|
|
95
|
+
primaryType: params.primaryType,
|
|
96
|
+
domain: params.domain,
|
|
97
|
+
});
|
|
98
|
+
// Use messenger to sign typed data
|
|
99
|
+
const signature = await __classPrivateFieldGet(this, _HyperLiquidWalletService_instances, "m", _HyperLiquidWalletService_signTypedMessage).call(this, {
|
|
100
|
+
from: currentAddress,
|
|
101
|
+
data: typedData,
|
|
102
|
+
});
|
|
103
|
+
return signature;
|
|
104
|
+
},
|
|
124
105
|
getChainId: async () => parseInt(getChainId(__classPrivateFieldGet(this, _HyperLiquidWalletService_isTestnet, "f")), 10),
|
|
125
106
|
};
|
|
126
107
|
}
|
|
@@ -197,36 +178,5 @@ async function _HyperLiquidWalletService_signTypedMessage(msgParams) {
|
|
|
197
178
|
msgParams,
|
|
198
179
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
199
180
|
'V4');
|
|
200
|
-
}, _HyperLiquidWalletService_signWithMaster =
|
|
201
|
-
/**
|
|
202
|
-
* Sign typed data with the master account via the keyring, resolving the
|
|
203
|
-
* selected account fresh so account switches cannot race the adapter.
|
|
204
|
-
*
|
|
205
|
-
* @param params - The typed-data signing request the SDK passed to the adapter.
|
|
206
|
-
* @returns The signature string.
|
|
207
|
-
*/
|
|
208
|
-
async function _HyperLiquidWalletService_signWithMaster(params) {
|
|
209
|
-
const currentEvmAccount = getSelectedEvmAccountFromMessenger(__classPrivateFieldGet(this, _HyperLiquidWalletService_messenger, "f"));
|
|
210
|
-
if (!currentEvmAccount?.address) {
|
|
211
|
-
throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);
|
|
212
|
-
}
|
|
213
|
-
const currentAddress = currentEvmAccount.address;
|
|
214
|
-
__classPrivateFieldGet(this, _HyperLiquidWalletService_deps, "f").debugLogger.log('HyperLiquidWalletService: Signing typed data (master fallback)', {
|
|
215
|
-
address: currentAddress,
|
|
216
|
-
primaryType: params.primaryType,
|
|
217
|
-
domain: params.domain,
|
|
218
|
-
});
|
|
219
|
-
const signature = await __classPrivateFieldGet(this, _HyperLiquidWalletService_instances, "m", _HyperLiquidWalletService_signTypedMessage).call(this, {
|
|
220
|
-
from: currentAddress,
|
|
221
|
-
data: {
|
|
222
|
-
domain: params.domain,
|
|
223
|
-
types: params.types,
|
|
224
|
-
primaryType: params.primaryType,
|
|
225
|
-
message: params.message,
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
return signature;
|
|
229
|
-
}, _HyperLiquidWalletService_isL1AgentAction = function _HyperLiquidWalletService_isL1AgentAction(primaryType, domainName) {
|
|
230
|
-
return primaryType === 'Agent' || domainName === 'Exchange';
|
|
231
181
|
};
|
|
232
182
|
//# sourceMappingURL=HyperLiquidWalletService.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HyperLiquidWalletService.mjs","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n hasProperty,\n isValidHexAddress,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport type { CaipAccountId, Hex } from '@metamask/utils';\n\nimport { getChainId } from '../constants/hyperLiquidConfig.js';\nimport { PERPS_ERROR_CODES } from '../perpsErrorCodes.js';\nimport type {\n HyperLiquidSignTypedDataParams,\n HyperLiquidWalletParams,\n} from './HyperLiquidClientService.js';\nimport type {\n PerpsPlatformDependencies,\n PerpsTypedMessageParams,\n} from '../types/index.js';\nimport type { PerpsControllerMessengerBase } from '../types/messenger.js';\nimport {\n getSelectedEvmAccountDetailsFromMessenger,\n getSelectedEvmAccountFromMessenger,\n} from '../utils/accountUtils.js';\n\n// Mirrors KeyringTypes from @metamask/keyring-controller. Inlined to keep this\n// service portable between mobile and the core monorepo.\nconst HARDWARE_KEYRING_TYPES = new Set<string>([\n 'Ledger Hardware',\n 'Trezor Hardware',\n 'OneKey Hardware',\n 'Lattice Hardware',\n 'QR Hardware Wallet Device',\n]);\n\n/**\n * A local signer for a HyperLiquid agent account, in the SDK-native\n * `AbstractEthersV6Signer` shape (positional EIP-712 arguments, message as\n * the signed value). Provided by the client (e.g. a local key stored in\n * memory) so agent actions never touch the keyring.\n */\nexport type AgentSigner = {\n /** The agent account address used as the actor for signed actions. */\n address: `0x${string}`;\n /**\n * Sign EIP-712 typed data with the agent key (positional ethers-style\n * arguments; `types` must not include `EIP712Domain`).\n *\n * @param domain - The EIP-712 domain.\n * @param types - The EIP-712 type definitions (without `EIP712Domain`).\n * @param value - The message payload to sign.\n * @returns The hex signature.\n */\n signTypedData(\n domain: HyperLiquidSignTypedDataParams['domain'],\n types: HyperLiquidSignTypedDataParams['types'],\n value: Record<string, unknown>,\n ): Promise<string>;\n};\n\n/**\n * Service for MetaMask wallet integration with HyperLiquid SDK\n * Provides wallet adapter that implements AbstractWindowEthereum interface\n */\nexport class HyperLiquidWalletService {\n #isTestnet: boolean;\n\n // Platform dependencies for observability\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #messenger: PerpsControllerMessengerBase;\n\n constructor(\n deps: PerpsPlatformDependencies,\n messenger: PerpsControllerMessengerBase,\n options: { isTestnet?: boolean } = {},\n ) {\n this.#deps = deps;\n this.#messenger = messenger;\n this.#isTestnet = options.isTestnet ?? false;\n }\n\n /**\n * Check if the keyring is currently unlocked\n *\n * @returns True if the keyring is unlocked and available for signing.\n */\n public isKeyringUnlocked(): boolean {\n return this.#messenger.call('KeyringController:getState').isUnlocked;\n }\n\n /**\n * Check whether the selected EVM account is backed by hardware.\n *\n * @returns True for MetaMask hardware keyrings; false for software accounts.\n */\n public isSelectedHardwareWallet(): boolean {\n const selectedEvmAccount = getSelectedEvmAccountDetailsFromMessenger(\n this.#messenger,\n );\n if (!selectedEvmAccount || !hasProperty(selectedEvmAccount, 'metadata')) {\n return false;\n }\n\n const metadata = selectedEvmAccount.metadata as\n | { keyring?: { type?: string } }\n | undefined;\n const keyringType = metadata?.keyring?.type;\n\n return Boolean(keyringType && HARDWARE_KEYRING_TYPES.has(keyringType));\n }\n\n /**\n * Sign typed data via DI keyring controller\n *\n * @param msgParams - The typed message parameters including data and sender address.\n * @returns The signature string.\n */\n async #signTypedMessage(msgParams: PerpsTypedMessageParams): Promise<string> {\n if (!this.isKeyringUnlocked()) {\n throw new Error(PERPS_ERROR_CODES.KEYRING_LOCKED);\n }\n // Cast needed: PerpsTypedMessageParams uses loose `data: unknown` type\n // while KeyringController uses strict TypedMessageParams / SignTypedDataVersion\n return this.#messenger.call(\n 'KeyringController:signTypedMessage',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n msgParams as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'V4' as any,\n );\n }\n\n /**\n * Sign typed data with the master account via the keyring, resolving the\n * selected account fresh so account switches cannot race the adapter.\n *\n * @param params - The typed-data signing request the SDK passed to the adapter.\n * @returns The signature string.\n */\n async #signWithMaster(params: HyperLiquidSignTypedDataParams): Promise<Hex> {\n const currentEvmAccount = getSelectedEvmAccountFromMessenger(\n this.#messenger,\n );\n\n if (!currentEvmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const currentAddress = currentEvmAccount.address as Hex;\n\n this.#deps.debugLogger.log(\n 'HyperLiquidWalletService: Signing typed data (master fallback)',\n {\n address: currentAddress,\n primaryType: params.primaryType,\n domain: params.domain,\n },\n );\n\n const signature = await this.#signTypedMessage({\n from: currentAddress,\n data: {\n domain: params.domain,\n types: params.types,\n primaryType: params.primaryType,\n message: params.message,\n },\n });\n\n return signature as Hex;\n }\n\n /**\n * Whether a typed-data signing request is an L1 (phantom-agent) action.\n *\n * The HyperLiquid SDK signs L1 actions (order/cancel/modify/TWAP/leverage/\n * margin/agentSetAbstraction) with EIP-712 primaryType `Agent` over domain\n * `{ name: \"Exchange\", version: \"1\", chainId: 1337 }`. Only these may be\n * signed by an agent key; every other shape (e.g. `approveBuilderFee`,\n * `userSetAbstraction`, `sendAsset`, `withdraw3` over the\n * `HyperliquidSignTransaction` domain) is a user-signed action that\n * authorizes the master account and must be signed by the master wallet.\n *\n * @param primaryType - The EIP-712 primary type of the signing request.\n * @param domainName - The EIP-712 domain name of the signing request.\n * @returns True when the request belongs to the agent-signable L1 class.\n */\n #isL1AgentAction(primaryType: string, domainName?: string): boolean {\n return primaryType === 'Agent' || domainName === 'Exchange';\n }\n\n /**\n * Create a wallet adapter backed by a local agent signer.\n *\n * The returned adapter keeps the params-style `signTypedData` shape the SDK\n * already accepts (viem local account), but routes by typed-data shape:\n * L1 (phantom-agent) actions — primaryType `Agent` over the `Exchange`\n * domain — are signed directly by the injected local signer with no keyring\n * contact; user-signed actions (`approveBuilderFee`, `userSetAbstraction`,\n * `sendAsset`, `withdraw3`, … over the `HyperliquidSignTransaction` domain)\n * are master-account authorizations and fall through to the master keyring\n * signing path, so hardware users get the normal device prompt. The SDK's\n * viem adapters inject an `EIP712Domain` entry into `types` before calling\n * params-style wallets; ethers-style signers reject that entry, so it is\n * stripped before delegating to the agent signer (the master path passes\n * `types` through unchanged, matching the pre-seam master adapter).\n *\n * @param agentSigner - The local agent signer to delegate L1 actions to.\n * @returns The agent wallet adapter.\n */\n public createAgentWalletAdapter(\n agentSigner: AgentSigner,\n ): HyperLiquidWalletParams {\n return {\n // The agent address is returned for identity purposes: the SDK only uses\n // it for local lock/nonce keying (`getWalletAddress`), never inside the\n // signed payload — HyperLiquid recovers the signer from the signature.\n address: agentSigner.address,\n signTypedData: async (\n params: HyperLiquidSignTypedDataParams,\n ): Promise<Hex> => {\n if (this.#isL1AgentAction(params.primaryType, params.domain?.name)) {\n const { EIP712Domain: _eip712Domain, ...types } = params.types;\n\n this.#deps.debugLogger.log(\n 'HyperLiquidWalletService: Signing typed data (agent mode)',\n {\n address: agentSigner.address,\n primaryType: params.primaryType,\n },\n );\n\n return (await agentSigner.signTypedData(\n params.domain,\n types,\n params.message,\n )) as Hex;\n }\n\n // User-signed action: master-account authorization, must be signed\n // by the master wallet (device prompt on hardware).\n return this.#signWithMaster(params);\n },\n getChainId: async (): Promise<number> =>\n parseInt(getChainId(this.#isTestnet), 10),\n };\n }\n\n /**\n * Create the master-keyring wallet adapter for the HyperLiquid SDK.\n *\n * This factory is synchronous and always signs via the selected master\n * account. Agent wallets are built separately with\n * {@link createAgentWalletAdapter}; the provider selects which adapter the\n * SDK clients use.\n *\n * @returns The wallet adapter with address, signTypedData, and getChainId methods.\n */\n public createWalletAdapter(): HyperLiquidWalletParams {\n // Get current EVM account via DI messenger\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const address = evmAccount.address as Hex;\n\n return {\n address,\n signTypedData: async (\n params: HyperLiquidSignTypedDataParams,\n ): Promise<Hex> => this.#signWithMaster(params),\n getChainId: async (): Promise<number> =>\n parseInt(getChainId(this.#isTestnet), 10),\n };\n }\n\n /**\n * Get current account ID using messenger\n *\n * @returns The CAIP account ID for the current EVM account.\n */\n public async getCurrentAccountId(): Promise<CaipAccountId> {\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const chainId = getChainId(this.#isTestnet);\n const caipAccountId: CaipAccountId = `eip155:${chainId}:${evmAccount.address}`;\n\n return caipAccountId;\n }\n\n /**\n * Get validated user address as Hex from account ID\n *\n * @param accountId - The CAIP account ID to extract the address from.\n * @returns The validated hex address.\n */\n public getUserAddress(accountId: CaipAccountId): Hex {\n const parsed = parseCaipAccountId(accountId);\n const address = parsed.address as Hex;\n\n if (!isValidHexAddress(address)) {\n throw new Error(PERPS_ERROR_CODES.INVALID_ADDRESS_FORMAT);\n }\n\n return address;\n }\n\n /**\n * Get user address with default fallback to current account\n *\n * @param accountId - Optional CAIP account ID; defaults to current account if omitted.\n * @returns The validated hex address.\n */\n public async getUserAddressWithDefault(\n accountId?: CaipAccountId,\n ): Promise<Hex> {\n const id = accountId ?? (await this.getCurrentAccountId());\n return this.getUserAddress(id);\n }\n\n /**\n * Update testnet mode\n *\n * @param isTestnet - Whether to enable testnet mode.\n */\n public setTestnetMode(isTestnet: boolean): void {\n this.#isTestnet = isTestnet;\n }\n\n /**\n * Check if running on testnet\n *\n * @returns True if the service is in testnet mode.\n */\n public isTestnetMode(): boolean {\n return this.#isTestnet;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"HyperLiquidWalletService.mjs","sourceRoot":"","sources":["../../src/services/HyperLiquidWalletService.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n hasProperty,\n isValidHexAddress,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport type { CaipAccountId, Hex } from '@metamask/utils';\n\nimport { getChainId } from '../constants/hyperLiquidConfig.js';\nimport { PERPS_ERROR_CODES } from '../perpsErrorCodes.js';\nimport type {\n PerpsPlatformDependencies,\n PerpsTypedMessageParams,\n} from '../types/index.js';\nimport type { PerpsControllerMessengerBase } from '../types/messenger.js';\nimport {\n getSelectedEvmAccountDetailsFromMessenger,\n getSelectedEvmAccountFromMessenger,\n} from '../utils/accountUtils.js';\n\n// Mirrors KeyringTypes from @metamask/keyring-controller. Inlined to keep this\n// service portable between mobile and the core monorepo.\nconst HARDWARE_KEYRING_TYPES = new Set<string>([\n 'Ledger Hardware',\n 'Trezor Hardware',\n 'OneKey Hardware',\n 'Lattice Hardware',\n 'QR Hardware Wallet Device',\n]);\n\n/**\n * Service for MetaMask wallet integration with HyperLiquid SDK\n * Provides wallet adapter that implements AbstractWindowEthereum interface\n */\nexport class HyperLiquidWalletService {\n #isTestnet: boolean;\n\n // Platform dependencies for observability\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #messenger: PerpsControllerMessengerBase;\n\n constructor(\n deps: PerpsPlatformDependencies,\n messenger: PerpsControllerMessengerBase,\n options: { isTestnet?: boolean } = {},\n ) {\n this.#deps = deps;\n this.#messenger = messenger;\n this.#isTestnet = options.isTestnet ?? false;\n }\n\n /**\n * Check if the keyring is currently unlocked\n *\n * @returns True if the keyring is unlocked and available for signing.\n */\n public isKeyringUnlocked(): boolean {\n return this.#messenger.call('KeyringController:getState').isUnlocked;\n }\n\n /**\n * Check whether the selected EVM account is backed by hardware.\n *\n * @returns True for MetaMask hardware keyrings; false for software accounts.\n */\n public isSelectedHardwareWallet(): boolean {\n const selectedEvmAccount = getSelectedEvmAccountDetailsFromMessenger(\n this.#messenger,\n );\n if (!selectedEvmAccount || !hasProperty(selectedEvmAccount, 'metadata')) {\n return false;\n }\n\n const metadata = selectedEvmAccount.metadata as\n | { keyring?: { type?: string } }\n | undefined;\n const keyringType = metadata?.keyring?.type;\n\n return Boolean(keyringType && HARDWARE_KEYRING_TYPES.has(keyringType));\n }\n\n /**\n * Sign typed data via DI keyring controller\n *\n * @param msgParams - The typed message parameters including data and sender address.\n * @returns The signature string.\n */\n async #signTypedMessage(msgParams: PerpsTypedMessageParams): Promise<string> {\n if (!this.isKeyringUnlocked()) {\n throw new Error(PERPS_ERROR_CODES.KEYRING_LOCKED);\n }\n // Cast needed: PerpsTypedMessageParams uses loose `data: unknown` type\n // while KeyringController uses strict TypedMessageParams / SignTypedDataVersion\n return this.#messenger.call(\n 'KeyringController:signTypedMessage',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n msgParams as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'V4' as any,\n );\n }\n\n /**\n * Create wallet adapter that implements AbstractViemJsonRpcAccount interface\n * Required by @nktkas/hyperliquid SDK for signing transactions\n *\n * @returns The wallet adapter with address, signTypedData, and getChainId methods.\n */\n public createWalletAdapter(): {\n address: Hex;\n signTypedData: (params: {\n domain: {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: Hex;\n };\n types: {\n [key: string]: { name: string; type: string }[];\n };\n primaryType: string;\n message: Record<string, unknown>;\n }) => Promise<Hex>;\n getChainId?: () => Promise<number>;\n } {\n // Get current EVM account via DI messenger\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const address = evmAccount.address as Hex;\n\n return {\n address,\n signTypedData: async (params: {\n domain: {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: Hex;\n };\n types: {\n [key: string]: { name: string; type: string }[];\n };\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<Hex> => {\n // Get FRESH account on every sign to handle account switches\n // This prevents race conditions where wallet adapter was created with old account\n const currentEvmAccount = getSelectedEvmAccountFromMessenger(\n this.#messenger,\n );\n\n if (!currentEvmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const currentAddress = currentEvmAccount.address as Hex;\n\n // Construct EIP-712 typed data\n const typedData = {\n domain: params.domain,\n types: params.types,\n primaryType: params.primaryType,\n message: params.message,\n };\n\n this.#deps.debugLogger.log(\n 'HyperLiquidWalletService: Signing typed data',\n {\n address: currentAddress,\n primaryType: params.primaryType,\n domain: params.domain,\n },\n );\n\n // Use messenger to sign typed data\n const signature = await this.#signTypedMessage({\n from: currentAddress,\n data: typedData,\n });\n\n return signature as Hex;\n },\n getChainId: async (): Promise<number> =>\n parseInt(getChainId(this.#isTestnet), 10),\n };\n }\n\n /**\n * Get current account ID using messenger\n *\n * @returns The CAIP account ID for the current EVM account.\n */\n public async getCurrentAccountId(): Promise<CaipAccountId> {\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n const chainId = getChainId(this.#isTestnet);\n const caipAccountId: CaipAccountId = `eip155:${chainId}:${evmAccount.address}`;\n\n return caipAccountId;\n }\n\n /**\n * Get validated user address as Hex from account ID\n *\n * @param accountId - The CAIP account ID to extract the address from.\n * @returns The validated hex address.\n */\n public getUserAddress(accountId: CaipAccountId): Hex {\n const parsed = parseCaipAccountId(accountId);\n const address = parsed.address as Hex;\n\n if (!isValidHexAddress(address)) {\n throw new Error(PERPS_ERROR_CODES.INVALID_ADDRESS_FORMAT);\n }\n\n return address;\n }\n\n /**\n * Get user address with default fallback to current account\n *\n * @param accountId - Optional CAIP account ID; defaults to current account if omitted.\n * @returns The validated hex address.\n */\n public async getUserAddressWithDefault(\n accountId?: CaipAccountId,\n ): Promise<Hex> {\n const id = accountId ?? (await this.getCurrentAccountId());\n return this.getUserAddress(id);\n }\n\n /**\n * Update testnet mode\n *\n * @param isTestnet - Whether to enable testnet mode.\n */\n public setTestnetMode(isTestnet: boolean): void {\n this.#isTestnet = isTestnet;\n }\n\n /**\n * Check if running on testnet\n *\n * @returns True if the service is in testnet mode.\n */\n public isTestnetMode(): boolean {\n return this.#isTestnet;\n }\n}\n"]}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced
|
|
15
15
|
* inside the injected signer bridge from client-managed key material.
|
|
16
16
|
*
|
|
17
|
-
* Signature routing
|
|
17
|
+
* Signature routing mirrors MYXWalletService: through
|
|
18
18
|
* `KeyringController:signPersonalMessage` when a messenger is available,
|
|
19
19
|
* or through an injected `LighterPersonalSigner` for headless use.
|
|
20
20
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LighterWalletService.cjs","sourceRoot":"","sources":["../../src/services/LighterWalletService.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;;;;;;;;;;;AAEH,2CAA6C;AAI7C,+DAA0D;AAM1D,+DAA8E;AAE9E,MAAa,oBAAoB;IAW/B,YACE,IAA+B,EAC/B,UAKI,EAAE;QAjBR,kDAAoB;QAEX,6CAAiC;QAEjC,kDAAiD;QAEjD,uDAAmD;QAEnD,kDAA+B;QAWtC,uBAAA,IAAI,8BAAS,IAAI,MAAA,CAAC;QAClB,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,wCAAmB,OAAO,CAAC,cAAc,MAAA,CAAC;QAC9C,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,IAAI,IAAI,MAAA,CAAC;IAC9C,CAAC;IAED,IAAI,OAAO;QACT,OAAO,uBAAA,IAAI,uCAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,UAAU,GAAG,IAAA,oDAAkC,EAAC,uBAAA,IAAI,uCAAW,CAAC,CAAC;YACvE,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,mBAAmB,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,UAAU,CAAC,OAAO,CAAC;QAC5B,CAAC;QACD,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,OAAO,uBAAA,IAAI,uCAAW,CAAC;QACzB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,mBAAmB,CAAC,OAAe;QACvC,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,EAAE,UAAU,EAAE,GAAG,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC1E,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,cAAc,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAS,CAAC;YAC7C,uBAAA,IAAI,kCAAM,CAAC,WAAW,CAAC,GAAG,CAAC,qCAAqC,EAAE;gBAChE,OAAO;aACR,CAAC,CAAC;YACH,kEAAkE;YAClE,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3D,OAAO,MAAM,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAC/B,uCAAuC,EACvC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CACxB,CAAC;QACJ,CAAC;QAED,IAAI,uBAAA,IAAI,4CAAgB,EAAE,CAAC;YACzB,OAAO,MAAM,uBAAA,IAAI,4CAAgB,MAApB,IAAI,EAAiB,OAAO,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAEM,cAAc,CAAC,SAAkB;QACtC,uBAAA,IAAI,mCAAc,SAAS,MAAA,CAAC;IAC9B,CAAC;IAEM,aAAa;QAClB,OAAO,uBAAA,IAAI,uCAAW,CAAC;IACzB,CAAC;CACF;AA3FD,oDA2FC","sourcesContent":["/**\n * LighterWalletService\n *\n * Routes the L1 signatures Lighter requires. The client-owned signer bridge\n * creates and stores the venue key; Core never receives its seed or private\n * key.\n *\n * Lighter's protocol needs two kinds of signatures:\n * 1. An EIP-191 `personal_sign` over the ChangePubKey plaintext produced by\n * the WASM signer — this registers the venue key on the account. The\n * signature is injected into the L2 transaction (`L1Sig`); the raw EVM\n * private key is never required, so hardware wallets are supported.\n * 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced\n * inside the injected signer bridge from client-managed key material.\n *\n * Signature routing
|
|
1
|
+
{"version":3,"file":"LighterWalletService.cjs","sourceRoot":"","sources":["../../src/services/LighterWalletService.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;;;;;;;;;;;AAEH,2CAA6C;AAI7C,+DAA0D;AAM1D,+DAA8E;AAE9E,MAAa,oBAAoB;IAW/B,YACE,IAA+B,EAC/B,UAKI,EAAE;QAjBR,kDAAoB;QAEX,6CAAiC;QAEjC,kDAAiD;QAEjD,uDAAmD;QAEnD,kDAA+B;QAWtC,uBAAA,IAAI,8BAAS,IAAI,MAAA,CAAC;QAClB,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,wCAAmB,OAAO,CAAC,cAAc,MAAA,CAAC;QAC9C,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,IAAI,IAAI,MAAA,CAAC;IAC9C,CAAC;IAED,IAAI,OAAO;QACT,OAAO,uBAAA,IAAI,uCAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,UAAU,GAAG,IAAA,oDAAkC,EAAC,uBAAA,IAAI,uCAAW,CAAC,CAAC;YACvE,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,mBAAmB,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,UAAU,CAAC,OAAO,CAAC;QAC5B,CAAC;QACD,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,OAAO,uBAAA,IAAI,uCAAW,CAAC;QACzB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,mBAAmB,CAAC,OAAe;QACvC,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,EAAE,UAAU,EAAE,GAAG,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC1E,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,cAAc,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAS,CAAC;YAC7C,uBAAA,IAAI,kCAAM,CAAC,WAAW,CAAC,GAAG,CAAC,qCAAqC,EAAE;gBAChE,OAAO;aACR,CAAC,CAAC;YACH,kEAAkE;YAClE,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3D,OAAO,MAAM,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAC/B,uCAAuC,EACvC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CACxB,CAAC;QACJ,CAAC;QAED,IAAI,uBAAA,IAAI,4CAAgB,EAAE,CAAC;YACzB,OAAO,MAAM,uBAAA,IAAI,4CAAgB,MAApB,IAAI,EAAiB,OAAO,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,sCAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAEM,cAAc,CAAC,SAAkB;QACtC,uBAAA,IAAI,mCAAc,SAAS,MAAA,CAAC;IAC9B,CAAC;IAEM,aAAa;QAClB,OAAO,uBAAA,IAAI,uCAAW,CAAC;IACzB,CAAC;CACF;AA3FD,oDA2FC","sourcesContent":["/**\n * LighterWalletService\n *\n * Routes the L1 signatures Lighter requires. The client-owned signer bridge\n * creates and stores the venue key; Core never receives its seed or private\n * key.\n *\n * Lighter's protocol needs two kinds of signatures:\n * 1. An EIP-191 `personal_sign` over the ChangePubKey plaintext produced by\n * the WASM signer — this registers the venue key on the account. The\n * signature is injected into the L2 transaction (`L1Sig`); the raw EVM\n * private key is never required, so hardware wallets are supported.\n * 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced\n * inside the injected signer bridge from client-managed key material.\n *\n * Signature routing mirrors MYXWalletService: through\n * `KeyringController:signPersonalMessage` when a messenger is available,\n * or through an injected `LighterPersonalSigner` for headless use.\n */\n\nimport { bytesToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport type { PerpsControllerMessenger } from '../PerpsController.js';\nimport { PERPS_ERROR_CODES } from '../perpsErrorCodes.js';\nimport type { PerpsPlatformDependencies } from '../types/index.js';\nimport type {\n LighterNetwork,\n LighterPersonalSigner,\n} from '../types/lighter-types.js';\nimport { getSelectedEvmAccountFromMessenger } from '../utils/accountUtils.js';\n\nexport class LighterWalletService {\n #isTestnet: boolean;\n\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #messenger: PerpsControllerMessenger | undefined;\n\n readonly #personalSigner: LighterPersonalSigner | undefined;\n\n readonly #l1Address: string | undefined;\n\n constructor(\n deps: PerpsPlatformDependencies,\n options: {\n isTestnet?: boolean;\n messenger?: PerpsControllerMessenger;\n personalSigner?: LighterPersonalSigner;\n l1Address?: string;\n } = {},\n ) {\n this.#deps = deps;\n this.#messenger = options.messenger;\n this.#personalSigner = options.personalSigner;\n this.#l1Address = options.l1Address;\n this.#isTestnet = options.isTestnet ?? true;\n }\n\n get network(): LighterNetwork {\n return this.#isTestnet ? 'testnet' : 'mainnet';\n }\n\n /**\n * Resolve the L1 address whose account owns the Lighter account.\n *\n * @returns The EVM address.\n */\n getUserAddress(): string {\n if (this.#messenger) {\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n return evmAccount.address;\n }\n if (this.#l1Address) {\n return this.#l1Address;\n }\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n /**\n * Sign an EIP-191 personal message with the user's L1 account.\n *\n * Routes through the keyring when a messenger is present, else the\n * injected headless signer.\n *\n * @param message - Plaintext message to sign.\n * @returns 65-byte signature as 0x-prefixed hex.\n */\n async signPersonalMessage(message: string): Promise<string> {\n if (this.#messenger) {\n const { isUnlocked } = this.#messenger.call('KeyringController:getState');\n if (!isUnlocked) {\n throw new Error(PERPS_ERROR_CODES.KEYRING_LOCKED);\n }\n const address = this.getUserAddress() as Hex;\n this.#deps.debugLogger.log('LighterWalletService: personal_sign', {\n address,\n });\n // KeyringController:signPersonalMessage expects hex-encoded data.\n const data = bytesToHex(new TextEncoder().encode(message));\n return await this.#messenger.call(\n 'KeyringController:signPersonalMessage',\n { from: address, data },\n );\n }\n\n if (this.#personalSigner) {\n return await this.#personalSigner(message);\n }\n\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n public setTestnetMode(isTestnet: boolean): void {\n this.#isTestnet = isTestnet;\n }\n\n public isTestnetMode(): boolean {\n return this.#isTestnet;\n }\n}\n"]}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced
|
|
14
14
|
* inside the injected signer bridge from client-managed key material.
|
|
15
15
|
*
|
|
16
|
-
* Signature routing
|
|
16
|
+
* Signature routing mirrors MYXWalletService: through
|
|
17
17
|
* `KeyringController:signPersonalMessage` when a messenger is available,
|
|
18
18
|
* or through an injected `LighterPersonalSigner` for headless use.
|
|
19
19
|
*/
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced
|
|
14
14
|
* inside the injected signer bridge from client-managed key material.
|
|
15
15
|
*
|
|
16
|
-
* Signature routing
|
|
16
|
+
* Signature routing mirrors MYXWalletService: through
|
|
17
17
|
* `KeyringController:signPersonalMessage` when a messenger is available,
|
|
18
18
|
* or through an injected `LighterPersonalSigner` for headless use.
|
|
19
19
|
*/
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced
|
|
14
14
|
* inside the injected signer bridge from client-managed key material.
|
|
15
15
|
*
|
|
16
|
-
* Signature routing
|
|
16
|
+
* Signature routing mirrors MYXWalletService: through
|
|
17
17
|
* `KeyringController:signPersonalMessage` when a messenger is available,
|
|
18
18
|
* or through an injected `LighterPersonalSigner` for headless use.
|
|
19
19
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LighterWalletService.mjs","sourceRoot":"","sources":["../../src/services/LighterWalletService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;;;;;;;;;AAEH,OAAO,EAAE,UAAU,EAAE,wBAAwB;AAI7C,OAAO,EAAE,iBAAiB,EAAE,+BAA8B;AAM1D,OAAO,EAAE,kCAAkC,EAAE,kCAAiC;AAE9E,MAAM,OAAO,oBAAoB;IAW/B,YACE,IAA+B,EAC/B,UAKI,EAAE;QAjBR,kDAAoB;QAEX,6CAAiC;QAEjC,kDAAiD;QAEjD,uDAAmD;QAEnD,kDAA+B;QAWtC,uBAAA,IAAI,8BAAS,IAAI,MAAA,CAAC;QAClB,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,wCAAmB,OAAO,CAAC,cAAc,MAAA,CAAC;QAC9C,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,IAAI,IAAI,MAAA,CAAC;IAC9C,CAAC;IAED,IAAI,OAAO;QACT,OAAO,uBAAA,IAAI,uCAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,UAAU,GAAG,kCAAkC,CAAC,uBAAA,IAAI,uCAAW,CAAC,CAAC;YACvE,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,UAAU,CAAC,OAAO,CAAC;QAC5B,CAAC;QACD,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,OAAO,uBAAA,IAAI,uCAAW,CAAC;QACzB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,mBAAmB,CAAC,OAAe;QACvC,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,EAAE,UAAU,EAAE,GAAG,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC1E,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAS,CAAC;YAC7C,uBAAA,IAAI,kCAAM,CAAC,WAAW,CAAC,GAAG,CAAC,qCAAqC,EAAE;gBAChE,OAAO;aACR,CAAC,CAAC;YACH,kEAAkE;YAClE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3D,OAAO,MAAM,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAC/B,uCAAuC,EACvC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CACxB,CAAC;QACJ,CAAC;QAED,IAAI,uBAAA,IAAI,4CAAgB,EAAE,CAAC;YACzB,OAAO,MAAM,uBAAA,IAAI,4CAAgB,MAApB,IAAI,EAAiB,OAAO,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAEM,cAAc,CAAC,SAAkB;QACtC,uBAAA,IAAI,mCAAc,SAAS,MAAA,CAAC;IAC9B,CAAC;IAEM,aAAa;QAClB,OAAO,uBAAA,IAAI,uCAAW,CAAC;IACzB,CAAC;CACF","sourcesContent":["/**\n * LighterWalletService\n *\n * Routes the L1 signatures Lighter requires. The client-owned signer bridge\n * creates and stores the venue key; Core never receives its seed or private\n * key.\n *\n * Lighter's protocol needs two kinds of signatures:\n * 1. An EIP-191 `personal_sign` over the ChangePubKey plaintext produced by\n * the WASM signer — this registers the venue key on the account. The\n * signature is injected into the L2 transaction (`L1Sig`); the raw EVM\n * private key is never required, so hardware wallets are supported.\n * 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced\n * inside the injected signer bridge from client-managed key material.\n *\n * Signature routing
|
|
1
|
+
{"version":3,"file":"LighterWalletService.mjs","sourceRoot":"","sources":["../../src/services/LighterWalletService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;;;;;;;;;AAEH,OAAO,EAAE,UAAU,EAAE,wBAAwB;AAI7C,OAAO,EAAE,iBAAiB,EAAE,+BAA8B;AAM1D,OAAO,EAAE,kCAAkC,EAAE,kCAAiC;AAE9E,MAAM,OAAO,oBAAoB;IAW/B,YACE,IAA+B,EAC/B,UAKI,EAAE;QAjBR,kDAAoB;QAEX,6CAAiC;QAEjC,kDAAiD;QAEjD,uDAAmD;QAEnD,kDAA+B;QAWtC,uBAAA,IAAI,8BAAS,IAAI,MAAA,CAAC;QAClB,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,wCAAmB,OAAO,CAAC,cAAc,MAAA,CAAC;QAC9C,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,MAAA,CAAC;QACpC,uBAAA,IAAI,mCAAc,OAAO,CAAC,SAAS,IAAI,IAAI,MAAA,CAAC;IAC9C,CAAC;IAED,IAAI,OAAO;QACT,OAAO,uBAAA,IAAI,uCAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACH,cAAc;QACZ,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,UAAU,GAAG,kCAAkC,CAAC,uBAAA,IAAI,uCAAW,CAAC,CAAC;YACvE,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,UAAU,CAAC,OAAO,CAAC;QAC5B,CAAC;QACD,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,OAAO,uBAAA,IAAI,uCAAW,CAAC;QACzB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,mBAAmB,CAAC,OAAe;QACvC,IAAI,uBAAA,IAAI,uCAAW,EAAE,CAAC;YACpB,MAAM,EAAE,UAAU,EAAE,GAAG,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YAC1E,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAS,CAAC;YAC7C,uBAAA,IAAI,kCAAM,CAAC,WAAW,CAAC,GAAG,CAAC,qCAAqC,EAAE;gBAChE,OAAO;aACR,CAAC,CAAC;YACH,kEAAkE;YAClE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3D,OAAO,MAAM,uBAAA,IAAI,uCAAW,CAAC,IAAI,CAC/B,uCAAuC,EACvC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CACxB,CAAC;QACJ,CAAC;QAED,IAAI,uBAAA,IAAI,4CAAgB,EAAE,CAAC;YACzB,OAAO,MAAM,uBAAA,IAAI,4CAAgB,MAApB,IAAI,EAAiB,OAAO,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IAEM,cAAc,CAAC,SAAkB;QACtC,uBAAA,IAAI,mCAAc,SAAS,MAAA,CAAC;IAC9B,CAAC;IAEM,aAAa;QAClB,OAAO,uBAAA,IAAI,uCAAW,CAAC;IACzB,CAAC;CACF","sourcesContent":["/**\n * LighterWalletService\n *\n * Routes the L1 signatures Lighter requires. The client-owned signer bridge\n * creates and stores the venue key; Core never receives its seed or private\n * key.\n *\n * Lighter's protocol needs two kinds of signatures:\n * 1. An EIP-191 `personal_sign` over the ChangePubKey plaintext produced by\n * the WASM signer — this registers the venue key on the account. The\n * signature is injected into the L2 transaction (`L1Sig`); the raw EVM\n * private key is never required, so hardware wallets are supported.\n * 2. Venue-key (Schnorr/ECgFp5) signatures over L2 transactions, produced\n * inside the injected signer bridge from client-managed key material.\n *\n * Signature routing mirrors MYXWalletService: through\n * `KeyringController:signPersonalMessage` when a messenger is available,\n * or through an injected `LighterPersonalSigner` for headless use.\n */\n\nimport { bytesToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport type { PerpsControllerMessenger } from '../PerpsController.js';\nimport { PERPS_ERROR_CODES } from '../perpsErrorCodes.js';\nimport type { PerpsPlatformDependencies } from '../types/index.js';\nimport type {\n LighterNetwork,\n LighterPersonalSigner,\n} from '../types/lighter-types.js';\nimport { getSelectedEvmAccountFromMessenger } from '../utils/accountUtils.js';\n\nexport class LighterWalletService {\n #isTestnet: boolean;\n\n readonly #deps: PerpsPlatformDependencies;\n\n readonly #messenger: PerpsControllerMessenger | undefined;\n\n readonly #personalSigner: LighterPersonalSigner | undefined;\n\n readonly #l1Address: string | undefined;\n\n constructor(\n deps: PerpsPlatformDependencies,\n options: {\n isTestnet?: boolean;\n messenger?: PerpsControllerMessenger;\n personalSigner?: LighterPersonalSigner;\n l1Address?: string;\n } = {},\n ) {\n this.#deps = deps;\n this.#messenger = options.messenger;\n this.#personalSigner = options.personalSigner;\n this.#l1Address = options.l1Address;\n this.#isTestnet = options.isTestnet ?? true;\n }\n\n get network(): LighterNetwork {\n return this.#isTestnet ? 'testnet' : 'mainnet';\n }\n\n /**\n * Resolve the L1 address whose account owns the Lighter account.\n *\n * @returns The EVM address.\n */\n getUserAddress(): string {\n if (this.#messenger) {\n const evmAccount = getSelectedEvmAccountFromMessenger(this.#messenger);\n if (!evmAccount?.address) {\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n return evmAccount.address;\n }\n if (this.#l1Address) {\n return this.#l1Address;\n }\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n /**\n * Sign an EIP-191 personal message with the user's L1 account.\n *\n * Routes through the keyring when a messenger is present, else the\n * injected headless signer.\n *\n * @param message - Plaintext message to sign.\n * @returns 65-byte signature as 0x-prefixed hex.\n */\n async signPersonalMessage(message: string): Promise<string> {\n if (this.#messenger) {\n const { isUnlocked } = this.#messenger.call('KeyringController:getState');\n if (!isUnlocked) {\n throw new Error(PERPS_ERROR_CODES.KEYRING_LOCKED);\n }\n const address = this.getUserAddress() as Hex;\n this.#deps.debugLogger.log('LighterWalletService: personal_sign', {\n address,\n });\n // KeyringController:signPersonalMessage expects hex-encoded data.\n const data = bytesToHex(new TextEncoder().encode(message));\n return await this.#messenger.call(\n 'KeyringController:signPersonalMessage',\n { from: address, data },\n );\n }\n\n if (this.#personalSigner) {\n return await this.#personalSigner(message);\n }\n\n throw new Error(PERPS_ERROR_CODES.NO_ACCOUNT_SELECTED);\n }\n\n public setTestnetMode(isTestnet: boolean): void {\n this.#isTestnet = isTestnet;\n }\n\n public isTestnetMode(): boolean {\n return this.#isTestnet;\n }\n}\n"]}
|