diff --git a/packages/dapp-example/src/App.tsx b/packages/dapp-example/src/App.tsx index 1178e65..4dd94d6 100644 --- a/packages/dapp-example/src/App.tsx +++ b/packages/dapp-example/src/App.tsx @@ -35,6 +35,11 @@ const App = () => { params: [], })) as string[]; + // also make sure it doesn't crash when no `params` is specified. This is allowed by EIP-1193 + (await injectedProvider.request({ + method: "eth_requestAccounts", + })) as string[]; + alert(result); }; diff --git a/packages/milkomeda-wsc-provider/src/algorandMethods/eth_accounts.ts b/packages/milkomeda-wsc-provider/src/algorandMethods/eth_accounts.ts index afe7c6f..4134e1d 100644 --- a/packages/milkomeda-wsc-provider/src/algorandMethods/eth_accounts.ts +++ b/packages/milkomeda-wsc-provider/src/algorandMethods/eth_accounts.ts @@ -4,15 +4,17 @@ import { JSON_RPC_ERROR_CODES, ProviderRpcError } from "../errors"; import { CustomMethod, MilkomedaProvider, RequestArguments } from "../types"; import { getActorAddress } from "../utils"; -const InputSchema = z.union([ - z.tuple([]), - z.tuple([ - z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), - ]), -]); +const InputSchema = z + .union([ + z.tuple([]), + z.tuple([ + z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), + ]), + ]) + .optional(); /** - * @dev Requests cardano address from the algorand wallet and transforms it to the Actor address + * @dev Requests algorand address from the algorand wallet and transforms it to the Actor address */ const eth_accounts: CustomMethod = async ( provider: MilkomedaProvider, @@ -37,7 +39,7 @@ const eth_accounts: CustomMethod = async ( try { if (!peraWallet.isConnected || algorandAccounts.length === 0) return []; - const [salt] = InputSchema.parse(params); + const [salt] = InputSchema.parse(params) ?? []; const [address] = algorandAccounts; diff --git a/packages/milkomeda-wsc-provider/src/algorandMethods/eth_requestAccounts.ts b/packages/milkomeda-wsc-provider/src/algorandMethods/eth_requestAccounts.ts index f23b583..e185d9b 100644 --- a/packages/milkomeda-wsc-provider/src/algorandMethods/eth_requestAccounts.ts +++ b/packages/milkomeda-wsc-provider/src/algorandMethods/eth_requestAccounts.ts @@ -4,15 +4,17 @@ import { JSON_RPC_ERROR_CODES, ProviderRpcError } from "../errors"; import { CustomMethod, MilkomedaProvider, RequestArguments } from "../types"; import { getActorAddress } from "../utils"; -const InputSchema = z.union([ - z.tuple([]), - z.tuple([ - z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), - ]), -]); +const InputSchema = z + .union([ + z.tuple([]), + z.tuple([ + z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), + ]), + ]) + .optional(); /** - * @dev Requests cardano address from the algorand wallet and transforms it to the Actor address + * @dev Requests cardano address from the Algorand wallet and transforms it to the Actor address */ const eth_requestAccounts: CustomMethod = async ( provider: MilkomedaProvider, @@ -35,7 +37,7 @@ const eth_requestAccounts: CustomMethod = async ( } try { - const [salt] = InputSchema.parse(params); + const [salt] = InputSchema.parse(params) ?? []; const [address] = provider.algorandAccounts.length === 0 diff --git a/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_accounts.ts b/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_accounts.ts index 19fab8d..52d527a 100644 --- a/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_accounts.ts +++ b/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_accounts.ts @@ -6,12 +6,14 @@ import { JSON_RPC_ERROR_CODES, ProviderRpcError } from "../errors"; import { CustomMethod, MilkomedaProvider, RequestArguments } from "../types"; import { getActorAddress } from "../utils"; -const InputSchema = z.union([ - z.tuple([]), - z.tuple([ - z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), - ]), -]); +const InputSchema = z + .union([ + z.tuple([]), + z.tuple([ + z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), + ]), + ]) + .optional(); /** * @dev Requests cardano address from injected cardano provider and transforms it to the Actor address @@ -38,7 +40,7 @@ const eth_accounts: CustomMethod = async ( return []; } - const [salt] = InputSchema.parse(params); + const [salt] = InputSchema.parse(params) ?? []; // After the page refresh the object needs to be enabled again await window.cardano.enable(); diff --git a/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_requestAccounts.ts b/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_requestAccounts.ts index d3c3e0c..a93fdb0 100644 --- a/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_requestAccounts.ts +++ b/packages/milkomeda-wsc-provider/src/cardanoMethods/eth_requestAccounts.ts @@ -6,15 +6,17 @@ import { JSON_RPC_ERROR_CODES, ProviderRpcError } from "../errors"; import { CustomMethod, MilkomedaProvider, RequestArguments } from "../types"; import { getActorAddress } from "../utils"; -const InputSchema = z.union([ - z.tuple([]), - z.tuple([ - z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), - ]), -]); +const InputSchema = z + .union([ + z.tuple([]), + z.tuple([ + z.string().refine((salt) => ethers.utils.isHexString(salt, 32), { message: "Invalid salt" }), + ]), + ]) + .optional(); /** - * @dev Requests cardano address from injected cardano provider and transforms it to the Actor address + * @dev Requests Cardano address from injected Cardano provider and transforms it to the Actor address */ const eth_requestAccounts: CustomMethod = async ( provider: MilkomedaProvider, @@ -34,7 +36,7 @@ const eth_requestAccounts: CustomMethod = async ( } try { - const [salt] = InputSchema.parse(params); + const [salt] = InputSchema.parse(params) ?? []; await window.cardano.enable(); diff --git a/packages/milkomeda-wsc-provider/src/errors.ts b/packages/milkomeda-wsc-provider/src/errors.ts index 8f57c8e..ae57c3c 100644 --- a/packages/milkomeda-wsc-provider/src/errors.ts +++ b/packages/milkomeda-wsc-provider/src/errors.ts @@ -1,3 +1,7 @@ +/** + * Errors must be `ProviderRpcError` as per EIP1193 + * https://eips.ethereum.org/EIPS/eip-1193#errors + */ export class ProviderRpcError extends Error { public name = "ProviderRpcError"; @@ -19,6 +23,8 @@ export const JSON_RPC_ERROR_CODES = { METHOD_NOT_SUPPORTED: -32004, LIMIT_EXCEEDED: -32005, JSON_RPC_VERSION_NOT_SUPPORTED: -32006, + // errors codes below come from the EIP-1193 standard + // https://eips.ethereum.org/EIPS/eip-1193#rpc-errors USER_REJECTED_REQUEST: 4001, UNAUTHORIZED: 4100, UNSUPPORTED_METHOD: 4200, diff --git a/packages/milkomeda-wsc-provider/src/provider.ts b/packages/milkomeda-wsc-provider/src/provider.ts index 1419ddb..5961a0c 100644 --- a/packages/milkomeda-wsc-provider/src/provider.ts +++ b/packages/milkomeda-wsc-provider/src/provider.ts @@ -11,6 +11,16 @@ export const PROVIDER_TYPES = { } as const; export type ProviderType = (typeof PROVIDER_TYPES)[keyof typeof PROVIDER_TYPES]; +/** + * A wrapper for EIP-1193 + * On top of its custom functions, you can use it as a standard EIP-1193 object + * ```ts + * await wscProvider.request({ + * method: "eth_requestAccounts", + * params: [], + * }) + * ``` + */ class Provider extends EventEmitter implements MilkomedaProvider { private readonly methods: { [key: string]: CustomMethod }; @@ -52,6 +62,8 @@ class Provider extends EventEmitter implements MilkomedaProvider { this.actorVersion = actorVersion; + // required to emit `connect` as per EIP1193 + // https://eips.ethereum.org/EIPS/eip-1193#connect-1 this.emit("connect"); } @@ -59,6 +71,10 @@ class Provider extends EventEmitter implements MilkomedaProvider { await this.setup(actorVersion); } + /** + * request method from EIP-1193 + * https://eips.ethereum.org/EIPS/eip-1193#request-1 + */ async request(payload: RequestArguments): Promise { if (payload.method in this.methods) { return this.methods[payload.method](this, payload);