diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 161efb9af..e0d2f55c0 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -2,7 +2,7 @@ name: Canary on: pull_request: branches: - - 'master' + - "master" merge_group: types: [checks_requested] @@ -23,10 +23,10 @@ jobs: fetch-tags: true - name: Setup node - uses: actions/setup-node@v6 + uses: actions/setup-node@v4 with: node-version: 24 - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: | @@ -60,10 +60,10 @@ jobs: fetch-tags: true - name: Setup node - uses: actions/setup-node@v6 + uses: actions/setup-node@v4 with: node-version: 24 - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: | diff --git a/packages/@magic-sdk/provider/src/modules/base-extension.ts b/packages/@magic-sdk/provider/src/modules/base-extension.ts index db797f514..4b3bc9251 100644 --- a/packages/@magic-sdk/provider/src/modules/base-extension.ts +++ b/packages/@magic-sdk/provider/src/modules/base-extension.ts @@ -15,9 +15,11 @@ function getPrototypeChain>(instance: T) { let currentProto = Object.getPrototypeOf(instance); const protos = [currentProto]; - while (currentProto !== BaseModule.prototype) { + while (currentProto && currentProto !== BaseModule.prototype) { currentProto = Object.getPrototypeOf(currentProto); + protos.push(currentProto); + } return protos; diff --git a/packages/@magic-sdk/provider/src/modules/wallet.ts b/packages/@magic-sdk/provider/src/modules/wallet.ts index 338613744..16a44c666 100644 --- a/packages/@magic-sdk/provider/src/modules/wallet.ts +++ b/packages/@magic-sdk/provider/src/modules/wallet.ts @@ -5,6 +5,8 @@ import { ConnectWithUIOptions, ConnectWithUiEvents, ShowUIPromiEvents, + Sign7702AuthorizationRequest, + Sign7702AuthorizationResponse, } from '@magic-sdk/types'; import { BaseModule } from './base-module'; import { createJsonRpcRequestPayload } from '../core/json-rpc'; @@ -76,4 +78,26 @@ export class WalletModule extends BaseModule { createJsonRpcRequestPayload(MagicPayloadMethod.SendGaslessTransaction, [address, transaction]), ); } + + /** + * Sign an EIP-7702 authorization to delegate the EOA to a smart contract implementation. + * This enables account abstraction features for externally owned accounts. + * + * @param params - The authorization parameters including contractAddress, chainId, and optional nonce + * @returns Promise resolving to the signed authorization with signature components (v, r, s) + * + * @example + * ```typescript + * const authorization = await magic.wallet.sign7702Authorization({ + * contractAddress: '0x000000004F43C49e93C970E84001853a70923B03', + * chainId: 1, + * nonce: 0 + * }); + * ``` + */ + public sign7702Authorization(params: Sign7702AuthorizationRequest) { + return this.request( + createJsonRpcRequestPayload(MagicPayloadMethod.Sign7702Authorization, [params]), + ); + } } diff --git a/packages/@magic-sdk/types/src/core/json-rpc-types.ts b/packages/@magic-sdk/types/src/core/json-rpc-types.ts index e4008e9d0..29054c4f3 100644 --- a/packages/@magic-sdk/types/src/core/json-rpc-types.ts +++ b/packages/@magic-sdk/types/src/core/json-rpc-types.ts @@ -130,6 +130,7 @@ export enum MagicPayloadMethod { EnableMFA = 'magic_auth_enable_mfa_flow', DisableMFA = 'magic_auth_disable_mfa_flow', GetMultichainPublicAddress = 'magic_get_multichain_public_address', + Sign7702Authorization = 'magic_wallet_sign_7702_authorization', } // Methods to not route if connected to third party wallet diff --git a/packages/@magic-sdk/types/src/modules/wallet-types.ts b/packages/@magic-sdk/types/src/modules/wallet-types.ts index b245a1110..96ccbbb1f 100644 --- a/packages/@magic-sdk/types/src/modules/wallet-types.ts +++ b/packages/@magic-sdk/types/src/modules/wallet-types.ts @@ -89,3 +89,63 @@ export interface GaslessTransactionRequest { export enum WalletEventOnReceived { WalletInfoFetched = 'Wallet/wallet-info-fetched', } + +/** + * Request parameters for EIP-7702 authorization signing + */ +export interface Sign7702AuthorizationRequest { + /** + * The smart contract implementation address the EOA delegates to + */ + contractAddress: string; + + /** + * The chain ID for the network (use 0 for universal cross-chain authorization) + */ + chainId: number; + + /** + * The nonce for the EOA account (transaction count) + */ + nonce?: number; +} + +/** + * Response from EIP-7702 authorization signing + */ +export interface Sign7702AuthorizationResponse { + /** + * The contract address that was authorized + */ + contractAddress: string; + + /** + * The chain ID for the authorization + */ + chainId: number; + + /** + * The nonce used in the authorization + */ + nonce: number; + + /** + * The v component of the signature (recovery id) + */ + v: number; + + /** + * The r component of the signature + */ + r: string; + + /** + * The s component of the signature + */ + s: string; + + /** + * Optional: Full signature as hex string + */ + signature?: string; +} diff --git a/packages/magic-sdk/package.json b/packages/magic-sdk/package.json index 187120f9f..3bd928d3d 100644 --- a/packages/magic-sdk/package.json +++ b/packages/magic-sdk/package.json @@ -29,8 +29,8 @@ ] }, "dependencies": { - "@magic-sdk/provider": "^31.2.0", - "@magic-sdk/types": "^25.2.0", + "@magic-sdk/provider": "^33.0.0", + "@magic-sdk/types": "^27.0.0", "localforage": "^1.7.4" }, "gitHead": "1ef062ea699d48d5e9a9375a93b7c147632b05ca" diff --git a/yarn.lock b/yarn.lock index d356a31e2..9dee4b424 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3318,6 +3318,20 @@ __metadata: languageName: unknown linkType: soft +"@magic-sdk/provider@^33.0.0, @magic-sdk/provider@workspace:packages/@magic-sdk/provider": + version: 0.0.0-use.local + resolution: "@magic-sdk/provider@workspace:packages/@magic-sdk/provider" + dependencies: + "@babel/plugin-transform-modules-commonjs": ^7.9.6 + "@magic-sdk/types": ^25.2.0 + eventemitter3: ^4.0.4 + localforage: ^1.7.4 + tslib: ^2.3.1 + peerDependencies: + localforage: ^1.7.4 + languageName: unknown + linkType: soft + "@magic-sdk/provider@npm:^29.5.0": version: 29.5.0 resolution: "@magic-sdk/provider@npm:29.5.0" @@ -3342,20 +3356,6 @@ __metadata: languageName: node linkType: hard -"@magic-sdk/provider@workspace:packages/@magic-sdk/provider": - version: 0.0.0-use.local - resolution: "@magic-sdk/provider@workspace:packages/@magic-sdk/provider" - dependencies: - "@babel/plugin-transform-modules-commonjs": ^7.9.6 - "@magic-sdk/types": ^25.2.0 - eventemitter3: ^4.0.4 - localforage: ^1.7.4 - tslib: ^2.3.1 - peerDependencies: - localforage: ^1.7.4 - languageName: unknown - linkType: soft - "@magic-sdk/react-native-bare@npm:^32.2.0": version: 32.2.0 resolution: "@magic-sdk/react-native-bare@npm:32.2.0" @@ -3491,6 +3491,12 @@ __metadata: languageName: unknown linkType: soft +"@magic-sdk/types@^27.0.0, @magic-sdk/types@workspace:packages/@magic-sdk/types": + version: 0.0.0-use.local + resolution: "@magic-sdk/types@workspace:packages/@magic-sdk/types" + languageName: unknown + linkType: soft + "@magic-sdk/types@npm:^24.21.0, @magic-sdk/types@npm:^24.22.0": version: 24.22.0 resolution: "@magic-sdk/types@npm:24.22.0" @@ -3505,12 +3511,6 @@ __metadata: languageName: node linkType: hard -"@magic-sdk/types@workspace:packages/@magic-sdk/types": - version: 0.0.0-use.local - resolution: "@magic-sdk/types@workspace:packages/@magic-sdk/types" - languageName: unknown - linkType: soft - "@motionone/animation@npm:^10.15.1, @motionone/animation@npm:^10.18.0": version: 10.18.0 resolution: "@motionone/animation@npm:10.18.0" @@ -14518,8 +14518,8 @@ __metadata: version: 0.0.0-use.local resolution: "magic-sdk@workspace:packages/magic-sdk" dependencies: - "@magic-sdk/provider": ^31.2.0 - "@magic-sdk/types": ^25.2.0 + "@magic-sdk/provider": ^33.0.0 + "@magic-sdk/types": ^27.0.0 localforage: ^1.7.4 languageName: unknown linkType: soft