Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix type errors #4

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"dependencies": {
"@consensys/starknet-snap": "^2.2.0",
"@metamask/types": "^1.1.0",
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer need types from here, as @metamask/providers provide more relevant types.

"@metamask/providers": "^13.1.0",
"ethers": "^6.7.1"
},
"devDependencies": {
Expand Down
135 changes: 76 additions & 59 deletions packages/core/src/wallet/metamask_snap/accounts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IMetaMaskInjectedProvider } from "."
import { UDC_ADDRESS } from "./constants"
import { SendTransactionParam } from "./types"
import { MetaMaskSigner } from "./signer"
import { MetaMaskInpageProvider } from "@metamask/providers"
import {
Abi,
AccountInterface,
Expand All @@ -17,6 +17,7 @@ import {
DeployAccountContractPayload,
DeployContractResponse,
DeployContractUDCResponse,
DeployTransactionReceiptResponse,
EstimateFeeAction,
EstimateFeeDetails,
EstimateFeeResponse,
Expand All @@ -26,15 +27,19 @@ import {
InvocationsDetails,
InvocationsDetailsWithNonce,
InvokeFunctionResponse,
MultiDeployContractResponse,
Nonce,
Provider,
ProviderInterface,
Signature,
SignerInterface,
SimulateTransactionDetails,
SimulateTransactionResponse,
TypedData,
UniversalDeployerContractPayload,
ec,
num,
parseUDCEvent,
stark,
typedData,
} from "starknet"
Expand All @@ -47,25 +52,34 @@ export class MetaMaskAccountWrapper
implements AccountInterface
{
address: string
provider: ProviderInterface
cairoVersion: CairoVersion
metaMaskInjectedProvider: IMetaMaskInjectedProvider
metaMaskInjectedProvider: MetaMaskInpageProvider
snapId: string
signer: SignerInterface

constructor(
address: string,
provider: ProviderInterface,
cairoVersion: CairoVersion = "0",
metamMaskInjectedProvider: IMetaMaskInjectedProvider,
metaMaskInjectedProvider: MetaMaskInpageProvider,
snapId: string,
) {
super(provider)

this.address = address
this.provider = provider
this.cairoVersion = cairoVersion
this.metaMaskInjectedProvider = metamMaskInjectedProvider
this.metaMaskInjectedProvider = metaMaskInjectedProvider
this.snapId = snapId
this.signer = new MetaMaskSigner()
}

deploy(
payload:
| UniversalDeployerContractPayload
| UniversalDeployerContractPayload[],
details?: InvocationsDetails | undefined,
): Promise<MultiDeployContractResponse> {
throw new Error("Method not implemented.")
}

async execute(
Expand All @@ -79,14 +93,17 @@ export class MetaMaskAccountWrapper
}

let { contractAddress, entrypoint, calldata } = transactions[0]
let nonce = await this.getNonce()

return await this.invokeFunction(
{
contractAddress,
entrypoint,
calldata,
},
{},
{
nonce,
},
)
}

Expand All @@ -102,37 +119,44 @@ export class MetaMaskAccountWrapper

const maxFee = details.maxFee ? toHex(details.maxFee) : null

const contractCallData = calldata ? calldata.join(",") : ""
const contractCallData = CallData.toHex(calldata).join(",")

const senderAddress = this.address
const chainId = toHex(await this.provider.getChainId())

const response = await this.metaMaskInjectedProvider.request<
SendTransactionParam,
string
>({
method: "wallet_invokeSnap",
params: {
snapId: this.snapId,
request: {
method: "starkNet_sendTransaction",
params: {
contractAddress,
contractFuncName: entrypoint,
contractCallData,
senderAddress,
maxFee,
chainId,
const chainId = toHex(await this.getChainId())

const response =
await this.metaMaskInjectedProvider.request<InvokeFunctionResponse>({
method: "wallet_invokeSnap",
params: {
snapId: this.snapId,
request: {
method: "starkNet_sendTransaction",
params: {
contractAddress,
contractFuncName: entrypoint,
contractCallData,
senderAddress,
maxFee,
chainId,
},
},
},
},
})
})

return response
if (!response) {
throw new Error("invalid response for starkNet_sendTransaction")
}
if (!response.transaction_hash) {
throw new Error(
"invalid response for starkNet_sendTransaction, transaction hash not found",
)
}

return { transaction_hash: response.transaction_hash }
}

async getNonce(blockIdentifier?: BlockIdentifier): Promise<Nonce> {
return this.provider.getNonceForAddress(this.address, blockIdentifier)
return this.getNonceForAddress(this.address, blockIdentifier)
}

public async getSuggestedMaxFee(
Expand Down Expand Up @@ -228,10 +252,10 @@ export class MetaMaskAccountWrapper
return getMessageHash(typedData, this.address)
}

// todo: the return type has to be fixed, i.e to be of type Signature and not
// todo(harsh): the return type has to be fixed, i.e to be of type Signature and not
// of type string
public async signMessage(typedData: TypedData): Promise<Signature> {
const signature = await this.metaMaskInjectedProvider.request({
const signature = (await this.metaMaskInjectedProvider.request({
method: "wallet_invokeSnap",
params: {
snapId: this.snapId,
Expand All @@ -240,41 +264,29 @@ export class MetaMaskAccountWrapper
params: {
typedDataMessage: JSON.stringify(typedData),
signerAddress: this.address,
chainId: await this.provider.getChainId(),
chainId: await this.getChainId(),
},
},
},
})
})) as unknown as string

return signature
return ec.starkCurve.Signature.fromDER(signature)
}

//todo(harsh): the below method should just use the UDC to deploy the account
async deployAccount(
_contractPayload: DeployAccountContractPayload,
_transactionsDetail?: InvocationsDetails | undefined,
): Promise<DeployContractResponse> {
const response = await this.metaMaskInjectedProvider.request({
method: "wallet_invokeSnap",
params: {
snapId: this.snapId,
request: {
method: "starkNet_createAccount",
params: {
deploy: true,
chainId: await this.provider.getChainId(),
},
},
},
})

return response
throw new Error("deploy account is not implemented yet")
}

// todo!()
public async declareAndDeploy(
_payload: DeclareAndDeployContractPayload,
_details?: InvocationsDetails | undefined,
): Promise<DeclareDeployUDCResponse> {
// todo!()
throw new Error("declare and deploy is not supported")
}

public async deployContract(
Expand All @@ -296,10 +308,14 @@ export class MetaMaskAccountWrapper
constructorCalldata,
} = udcPayload[0]

const compiledConstructorCallData = CallData.compile(constructorCalldata)
const classHashHex = "0x" + classHash.toString(16)

const compiledConstructorCallData = CallData.toHex(
constructorCalldata ? constructorCalldata : [],
)
const deploySalt = salt ? salt : stark.randomAddress()

const response = await this.metaMaskInjectedProvider.request({
const response = (await this.metaMaskInjectedProvider.request({
method: "wallet_invokeSnap",
params: {
snapId: this.snapId,
Expand All @@ -309,28 +325,29 @@ export class MetaMaskAccountWrapper
contractAddress: UDC_ADDRESS,
contractFuncName: "deployContract",
contractCallData: [
"0x" + classHash.toString(16),
classHashHex,
deploySalt,
toCairoBool(unique),
"0x" + compiledConstructorCallData.length.toString(16),
...compiledConstructorCallData,
].join(","),
senderAddress: this.address,
chainId: await this.provider.getChainId(),
chainId: await this.getChainId(),
},
},
},
})
})) as unknown as InvokeFunctionResponse

return response
const txReceipt = await this.waitForTransaction(response.transaction_hash)
return parseUDCEvent(txReceipt as DeployTransactionReceiptResponse)
}

// declare isn't allowed via the exposed RPC as of now
// todo!()
public async declare(
_contractPayload: DeclareContractPayload,
_transactionsDetail?: InvocationsDetails | undefined,
): Promise<DeclareContractResponse> {
// todo!()
throw new Error("declare isn't implemented as of now")
}
}
48 changes: 23 additions & 25 deletions packages/core/src/wallet/metamask_snap/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,28 @@ import {
} from "../../StarknetWindowObject"
import { MetaMaskAccountWrapper } from "./accounts"
import { CHAIN_ID_TESTNET } from "./constants"
import { ChainId, SnapRequest } from "./types"
import { ChainId, RequestSnapResponse } from "./types"
import {
AccContract,
Network,
} from "@consensys/starknet-snap/src/types/snapState"
import { JsonRpcResponse } from "@metamask/types"
import { MetaMaskInpageProvider } from "@metamask/providers"
import { AccountInterface, Provider, ProviderInterface } from "starknet"

export type JsonRpcRequestSnapParam = {
[key in `npm:${string}`]: {
version?: string
}
}

export interface IMetaMaskInjectedProvider {
request<P, T>(arg: SnapRequest<P>): Promise<JsonRpcResponse<T>>
}

export class MetaMaskSnap implements IStarknetWindowObject {
id: string
name: string
version: string
icon: string
metamaskProvider: IMetaMaskInjectedProvider
metamaskProvider: MetaMaskInpageProvider
account?: AccountInterface | undefined
provider?: ProviderInterface | undefined
selectedAddress?: string | undefined
chainId?: string | undefined
snapId: string
isConnected?: boolean

constructor(metamaskProvider: IMetaMaskInjectedProvider) {
constructor(metamaskProvider: MetaMaskInpageProvider) {
this.id = "metamask"
this.name = "Metamask"
this.version = "v0.0.1"
Expand All @@ -49,18 +39,28 @@ export class MetaMaskSnap implements IStarknetWindowObject {
this.chainId = CHAIN_ID_TESTNET
}

async request<T extends RpcMessage>(
call: Omit<T, "result">,
): Promise<T["result"]> {
throw new Error("method not implemented")
}

async enable(
options?: { starknetVersion?: "v4" | "v5" | undefined } | undefined,
) {
const response = await this.metamaskProvider.request({
const response = await this.metamaskProvider.request<RequestSnapResponse>({
method: "wallet_requestSnaps",
params: {
[this.snapId]: {},
},
})

if (response.error) {
throw response.error
if (typeof this.chainId === "undefined") {
throw new Error("chain id is undefined")
}

if (!response) {
throw new Error("the snap was not found")
}

const snapResponse = response[this.snapId]
Expand Down Expand Up @@ -95,6 +95,12 @@ export class MetaMaskSnap implements IStarknetWindowObject {
)
this.chainId = await this.provider.getChainId()
}

if (!this.selectedAddress) {
throw new Error("")
}

return [this.selectedAddress]
}

async isPreauthorized() {
Expand All @@ -113,14 +119,6 @@ export class MetaMaskSnap implements IStarknetWindowObject {
throw new Error("event handler is not implemented")
}

// Snap needs to have implementation for wallet_watchAsset
// The method for adding new chain needs to be adjusted as well,
// where we should not ask the class hash of account contract
async request<T extends RpcMessage>(call: Omit<T, "result">) {
// todo!()
throw new Error("request is not implemented")
}

private async getNetworkInfo(chainId: ChainId): Promise<Network | undefined> {
const response = (await this.metamaskProvider.request({
method: "wallet_invokeSnap",
Expand Down
Loading