diff --git a/packages/account/src/account.ts b/packages/account/src/account.ts index 77105c6e9..362efd656 100644 --- a/packages/account/src/account.ts +++ b/packages/account/src/account.ts @@ -880,10 +880,11 @@ export class Account { chainId: ethers.BigNumberish, quote?: FeeQuote, pstatus?: AccountStatus, - callback?: (bundle: commons.transaction.IntendedTransactionBundle) => void + callback?: (bundle: commons.transaction.IntendedTransactionBundle) => void, + projectAccessKey?: string ): Promise { if (!Array.isArray(signedBundle)) { - return this.sendSignedTransactions([signedBundle], chainId, quote, pstatus, callback) + return this.sendSignedTransactions([signedBundle], chainId, quote, pstatus, callback, projectAccessKey) } const status = pstatus || (await this.status(chainId)) this.mustBeFullyMigrated(status) @@ -891,7 +892,7 @@ export class Account { const decoratedBundle = await this.decorateTransactions(signedBundle, status, chainId) callback?.(decoratedBundle) - return this.relayer(chainId).relay(decoratedBundle, quote) + return this.relayer(chainId).relay(decoratedBundle, quote, undefined, projectAccessKey) } async fillGasLimits( @@ -910,6 +911,7 @@ export class Account { status?: AccountStatus, options?: { simulate?: boolean + projectAccessKey?: string } ): Promise<{ options: FeeOption[] @@ -952,12 +954,14 @@ export class Account { chainId: ethers.BigNumberish stubSignatureOverrides: Map simulateForFeeOptions?: boolean + projectAccessKey?: string }): Promise { const status = await this.status(args.chainId) const transactions = await this.fillGasLimits(args.txs, args.chainId, status) const gasRefundQuote = await this.gasRefundQuotes(transactions, args.chainId, args.stubSignatureOverrides, status, { - simulate: args.simulateForFeeOptions + simulate: args.simulateForFeeOptions, + projectAccessKey: args.projectAccessKey }) const flatDecorated = commons.transaction.unwind(this.address, gasRefundQuote.decorated.transactions) @@ -978,6 +982,7 @@ export class Account { options?: { nonceSpace?: ethers.BigNumberish serial?: boolean + projectAccessKey?: string } ): Promise { const status = await this.status(chainId) @@ -994,7 +999,7 @@ export class Account { } bundles.push(...childBundles.filter(b => b.transactions.length > 0)) - return this.sendSignedTransactions(bundles, chainId, quote, undefined, callback) + return this.sendSignedTransactions(bundles, chainId, quote, undefined, callback, options?.projectAccessKey) } async signTypedData( diff --git a/packages/provider/src/transports/base-provider-transport.ts b/packages/provider/src/transports/base-provider-transport.ts index a09038eca..6e0199e0e 100644 --- a/packages/provider/src/transports/base-provider-transport.ts +++ b/packages/provider/src/transports/base-provider-transport.ts @@ -46,10 +46,14 @@ export abstract class BaseProviderTransport implements ProviderTransport { protected _init: InitState protected _registered: boolean - constructor() { + readonly projectAccessKey?: string + + constructor(projectAccessKey?: string) { this.state = OpenState.CLOSED this._registered = false this._init = InitState.NIL + + this.projectAccessKey = projectAccessKey } get registered(): boolean { @@ -113,7 +117,8 @@ export abstract class BaseProviderTransport implements ProviderTransport { type: EventType.MESSAGE, data: request, chainId: request.chainId, - clientVersion: VERSION + clientVersion: VERSION, + projectAccessKey: this.projectAccessKey }) return response.data diff --git a/packages/provider/src/transports/mux-transport/mux-message-provider.ts b/packages/provider/src/transports/mux-transport/mux-message-provider.ts index f5f4a13b0..866e78a1b 100644 --- a/packages/provider/src/transports/mux-transport/mux-message-provider.ts +++ b/packages/provider/src/transports/mux-transport/mux-message-provider.ts @@ -61,17 +61,19 @@ export function isMuxTransportTemplate(obj: any): obj is MuxTransportTemplate { export class MuxMessageProvider implements ProviderTransport { private messageProviders: ProviderTransport[] private provider: ProviderTransport | undefined + private projectAccessKey?: string - constructor(...messageProviders: ProviderTransport[]) { + constructor(messageProviders: ProviderTransport[] = [], projectAccessKey?: string) { this.messageProviders = messageProviders this.provider = undefined + this.projectAccessKey = projectAccessKey } - static new(template: MuxTransportTemplate): MuxMessageProvider { + static new(template: MuxTransportTemplate, projectAccessKey?: string): MuxMessageProvider { const muxMessageProvider = new MuxMessageProvider() if (template.windowTransport?.enabled && typeof window === 'object' && template.walletAppURL) { - const windowMessageProvider = new WindowMessageProvider(template.walletAppURL) + const windowMessageProvider = new WindowMessageProvider(template.walletAppURL, projectAccessKey) muxMessageProvider.add(windowMessageProvider) } diff --git a/packages/provider/src/transports/wallet-request-handler.ts b/packages/provider/src/transports/wallet-request-handler.ts index 6b18e9e27..911e9c089 100644 --- a/packages/provider/src/transports/wallet-request-handler.ts +++ b/packages/provider/src/transports/wallet-request-handler.ts @@ -226,7 +226,9 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq const result = await this.request({ method: message.data.method, params: message.data.params, - chainId: message.chainId + chainId: message.chainId, + origin: message.origin, + projectAccessKey: message.projectAccessKey }) return { @@ -241,7 +243,13 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq } } - async request(request: { method: string; params?: any[]; chainId?: number }): Promise { + async request(request: { + method: string + params?: any[] + chainId?: number + origin?: string + projectAccessKey?: string + }): Promise { await this.getAccount() try { @@ -344,7 +352,8 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq message: ethers.getBytes(prefixedMessage), eip6492: sequenceVerified }, - this.connectOptions + request.origin, + request.projectAccessKey ) } @@ -397,7 +406,8 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq typedData: typedData, eip6492: sequenceVerified }, - this.connectOptions + request.origin, + request.projectAccessKey ) } @@ -431,7 +441,12 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq txnHash = txnResponse?.hash ?? '' } else { // prompt user to provide the response - txnHash = await this.prompter.promptSendTransaction(transactionParams, request.chainId, this.connectOptions) + txnHash = await this.prompter.promptSendTransaction( + transactionParams, + request.chainId, + request.origin, + request.projectAccessKey + ) } if (txnHash) { @@ -461,7 +476,12 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq // we will want to resolveProperties the big number values to hex strings return await account.signTransactions(transaction, request.chainId ?? this.defaultChainId()) } else { - return await this.prompter.promptSignTransaction(transaction, request.chainId, this.connectOptions) + return await this.prompter.promptSignTransaction( + transaction, + request.chainId, + request.origin, + request.projectAccessKey + ) } } @@ -800,7 +820,8 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq prompter: WalletUserPrompter, account: Account, sequenceVerified: boolean, - chainId?: number + chainId?: number, + origin?: string ): Promise { // check if wallet is deployed and up to date, if not, prompt user to deploy // if no chainId is provided, we'll assume the wallet is auth chain wallet and is up to date @@ -817,7 +838,7 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq return true } - const promptResult = await prompter.promptConfirmWalletDeploy(chainId, this.connectOptions) + const promptResult = await prompter.promptConfirmWalletDeploy(chainId, origin) // if client returned true, check again to make sure wallet is deployed and up to date if (promptResult) { @@ -837,15 +858,22 @@ export class WalletRequestHandler implements EIP1193Provider, ProviderMessageReq export interface WalletUserPrompter { getDefaultChainId(): number - - promptConnect(options?: ConnectOptions): Promise - promptSignInConnect(options?: ConnectOptions): Promise - - promptSignMessage(message: MessageToSign, options?: ConnectOptions): Promise - promptSignTransaction(txn: commons.transaction.Transactionish, chainId?: number, options?: ConnectOptions): Promise - promptSendTransaction(txn: commons.transaction.Transactionish, chainId?: number, options?: ConnectOptions): Promise - promptConfirmWalletDeploy(chainId: number, options?: ConnectOptions): Promise - + promptConnect(connectOptions?: ConnectOptions): Promise + promptSignInConnect(connectOptions?: ConnectOptions): Promise + promptSignMessage(message: MessageToSign, origin?: string, projectAccessKey?: string): Promise + promptSignTransaction( + txn: commons.transaction.Transactionish, + chainId?: number, + origin?: string, + projectAccessKey?: string + ): Promise + promptSendTransaction( + txn: commons.transaction.Transactionish, + chainId?: number, + origin?: string, + projectAccessKey?: string + ): Promise + promptConfirmWalletDeploy(chainId: number, origin?: string): Promise promptChangeNetwork(chainId: number): Promise } diff --git a/packages/provider/src/transports/window-transport/window-message-handler.ts b/packages/provider/src/transports/window-transport/window-message-handler.ts index 87a279627..dd7bf38f9 100644 --- a/packages/provider/src/transports/window-transport/window-message-handler.ts +++ b/packages/provider/src/transports/window-transport/window-message-handler.ts @@ -99,6 +99,9 @@ export class WindowMessageHandler extends BaseWalletTransport { return } + // Set the origin on the request + request.origin ??= event.origin + logger.debug('RECEIVED MESSAGE', request) // Record event origin for valid init ack diff --git a/packages/provider/src/transports/window-transport/window-message-provider.ts b/packages/provider/src/transports/window-transport/window-message-provider.ts index 2c4d3b695..17923bfb0 100644 --- a/packages/provider/src/transports/window-transport/window-message-provider.ts +++ b/packages/provider/src/transports/window-transport/window-message-provider.ts @@ -10,8 +10,8 @@ export class WindowMessageProvider extends BaseProviderTransport { private walletURL: URL private walletWindow: Window | null - constructor(walletAppURL: string) { - super() + constructor(walletAppURL: string, projectAccessKey?: string) { + super(projectAccessKey) this.walletURL = new URL(walletAppURL) } diff --git a/packages/provider/src/types.ts b/packages/provider/src/types.ts index 4475a48ba..eca311c16 100644 --- a/packages/provider/src/types.ts +++ b/packages/provider/src/types.ts @@ -62,6 +62,7 @@ export interface ProviderMessage { chainId?: number // chain id which the message is intended origin?: string // origin of the message clientVersion: string // client version of the message + projectAccessKey?: string // project access key } export type ProviderMessageRequest = ProviderMessage diff --git a/packages/relayer/src/index.ts b/packages/relayer/src/index.ts index 504a2917e..95a8eb287 100644 --- a/packages/relayer/src/index.ts +++ b/packages/relayer/src/index.ts @@ -40,7 +40,8 @@ export interface Relayer { relay( signedTxs: commons.transaction.IntendedTransactionBundle, quote?: FeeQuote, - waitForReceipt?: boolean + waitForReceipt?: boolean, + projectAccessKey?: string ): Promise // wait for transaction confirmation diff --git a/packages/relayer/src/rpc-relayer/index.ts b/packages/relayer/src/rpc-relayer/index.ts index 1b3a97d3a..b230387ce 100644 --- a/packages/relayer/src/rpc-relayer/index.ts +++ b/packages/relayer/src/rpc-relayer/index.ts @@ -61,7 +61,7 @@ export class RpcRelayer implements Relayer { } // before the request is made - init!.headers = { ...init!.headers, ...headers } + init!.headers = { ...headers, ...init!.headers } return fetch(input, init) } @@ -160,14 +160,18 @@ export class RpcRelayer implements Relayer { data: ethers.BytesLike, options?: { simulate?: boolean + projectAccessKey?: string } ): Promise<{ options: FeeOption[]; quote?: FeeQuote }> { - const { options: feeOptions, quote } = await this.service.feeOptions({ - wallet: entrypoint, - to: entrypoint, - data: ethers.hexlify(data), - simulate: options?.simulate - }) + const { options: feeOptions, quote } = await this.service.feeOptions( + { + wallet: entrypoint, + to: entrypoint, + data: ethers.hexlify(data), + simulate: options?.simulate + }, + { ...(options?.projectAccessKey ? { 'X-Access-Key': options.projectAccessKey } : undefined) } + ) return { options: feeOptions, quote: { _tag: 'FeeQuote', _quote: quote } } } @@ -190,7 +194,8 @@ export class RpcRelayer implements Relayer { async relay( signedTxs: commons.transaction.IntendedTransactionBundle, quote?: FeeQuote, - waitForReceipt: boolean = true + waitForReceipt: boolean = true, + projectAccessKey?: string ): Promise> { logger.info( `[rpc-relayer/relay] relaying signed meta-transactions ${JSON.stringify(signedTxs, bigintReplacer)} with quote ${JSON.stringify(quote, bigintReplacer)}` @@ -211,14 +216,17 @@ export class RpcRelayer implements Relayer { } const data = commons.transaction.encodeBundleExecData(signedTxs) - const metaTxn = await this.service.sendMetaTxn({ - call: { - walletAddress: signedTxs.intent.wallet, - contract: signedTxs.entrypoint, - input: data + const metaTxn = await this.service.sendMetaTxn( + { + call: { + walletAddress: signedTxs.intent.wallet, + contract: signedTxs.entrypoint, + input: data + }, + quote: typecheckedQuote }, - quote: typecheckedQuote - }) + { ...(projectAccessKey ? { 'X-Access-Key': projectAccessKey } : undefined) } + ) logger.info(`[rpc-relayer/relay] got relay result ${JSON.stringify(metaTxn, bigintReplacer)}`)