From 0a257532f35152b60ebf88de8c2781bad253579e Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Mon, 2 Oct 2023 18:39:35 +0300 Subject: [PATCH 01/16] feat: decouple from snjs 1. Implemented JSON-RPC SNIP (https://community.starknet.io/t/snip-standardizing-starknet-wallet-connections-with-write-api-and-json-rpc-integration/98049) 2. Decoupled get-starknet-core from snjs 3. Added silent mode to wallet-window connection --- packages/core/package.json | 10 - packages/core/src/StarknetWindowObject.ts | 203 ++++++++++++++-- packages/core/src/__test__/wallet.mock.ts | 2 +- packages/core/src/main.ts | 18 +- packages/core/src/wallet/isWalletObject.ts | 1 - packages/ui/src/main.ts | 10 +- pnpm-lock.yaml | 261 ++++++--------------- 7 files changed, 272 insertions(+), 233 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 0cec766..5de1af1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -32,19 +32,9 @@ "devDependencies": { "c8": "^7.12.0", "happy-dom": "^6.0.4", - "starknet": "^5.18.0", - "starknet4": "npm:starknet@4.22.0", "typescript": "^4.6.4", "vite": "^3.0.0", "vite-plugin-dts": "^1.4.0", "vitest": "^0.19.1" - }, - "peerDependencies": { - "starknet": "^5.18.0" - }, - "peerDependenciesMeta": { - "starknet": { - "optional": false - } } } diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index ca6b002..e6deaae 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -1,10 +1,49 @@ -import type { AccountInterface, ProviderInterface } from "starknet" -import type { - AccountInterface as AccountInterfaceV4, - ProviderInterface as ProviderInterfaceV4, -} from "starknet4" +type FELT = string -export type AccountChangeEventHandler = (accounts: string[]) => void +type SIERRA_ENTRY_POINT = { + selector: FELT + function_idx: number +} + +type StarkNetMerkleType = { + name: string + type: "merkletree" + contains: string +} + +/** + * A single type, as part of a struct. The `type` field can be any of the EIP-712 supported types. + * + * Note that the `uint` and `int` aliases like in Solidity, and fixed point numbers are not supported by the EIP-712 + * standard. + */ +type StarkNetType = + | { + name: string + type: string + } + | StarkNetMerkleType + +/** + * The EIP712 domain struct. Any of these fields are optional, but it must contain at least one field. + */ +interface StarkNetDomain extends Record { + name?: string + version?: string + chainId?: string | number +} + +/** + * The complete typed data, with all the structs, domain data, primary type of the message, and the message itself. + */ +interface TypedData { + types: Record + primaryType: string + domain: StarkNetDomain + message: Record +} + +export type AccountChangeEventHandler = (accounts?: string[]) => void export type NetworkChangeEventHandler = (network?: string) => void @@ -18,8 +57,112 @@ export type WalletEvents = handler: NetworkChangeEventHandler } -// EIP-747: -// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-747.md +/** + * INVOKE_TXN_V1 + * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + */ +export interface AddInvokeTransactionParameters { + /** + * The data expected by the account's `execute` function (in most use-cases, + * this includes the called contract address and a function selector) + */ + calldata: FELT[] +} +export interface AddInvokeTransactionResult { + /** + * The hash of the invoke transaction + */ + transaction_hash: FELT +} + +/** + * BROADCASTED_DECLARE_TXN_V2 + * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + */ +export interface AddDeclareTransactionParameters { + /** + * The hash of the Cairo assembly resulting from the Sierra compilation + */ + compiled_class_hash: FELT + contract_class: { + /** + * The list of Sierra instructions of which the program consists + */ + sierra_program: FELT[] + /** + * The version of the contract class object. Currently, the Starknet OS supports version 0.1.0 + */ + contract_class_version: string + /** + * Entry points by type + */ + entry_points_by_type: { + CONSTRUCTOR: SIERRA_ENTRY_POINT[] + EXTERNAL: SIERRA_ENTRY_POINT[] + L1_HANDLER: SIERRA_ENTRY_POINT[] + } + /** + * The class ABI, as supplied by the user declaring the class + */ + abi?: string + } +} +export interface AddDeclareTransactionResult { + /** + * The hash of the declare transaction + */ + transaction_hash: FELT + /** + * The hash of the declared class + */ + class_hash: FELT +} + +/** + * DEPLOY_ACCOUNT_TXN_V1 + * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + */ +export interface AddDeployAccountTransactionParameters { + /** + * The salt for the address of the deployed contract + */ + contract_address_salt: FELT + /** + * The parameters passed to the constructor + */ + constructor_calldata: FELT[] + /** + * The hash of the deployed contract's class + */ + class_hash: FELT +} +export interface AddDeployAccountTransactionResult { + /** + * The hash of the deploy transaction + */ + transaction_hash: FELT + /** + * The address of the new contract + */ + contract_address: FELT +} + +/** + * EIP-1102: + * @see https://eips.ethereum.org/EIPS/eip-1102 + */ +export interface RequestAccountsParameters { + /** + * If true, the wallet will not show the wallet-unlock UI in case of a locked wallet, + * nor the dApp-approve UI in case of a non-allowed dApp. + */ + silentMode?: boolean +} + +/** + * EIP-747: + * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-747.md + */ export interface WatchAssetParameters { type: "ERC20" // The asset's interface, e.g. 'ERC20' options: { @@ -31,9 +174,10 @@ export interface WatchAssetParameters { } } -// EIP-3085 -// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3085.md - +/** + * EIP-3085: + * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3085.md + */ export interface AddStarknetChainParameters { id: string chainId: string // A 0x-prefixed hexadecimal string @@ -51,11 +195,16 @@ export interface AddStarknetChainParameters { iconUrls?: string[] // Currently ignored. } -export interface SwitchStarknetChainParameter { +export interface SwitchStarknetChainParameters { chainId: string // A 0x-prefixed hexadecimal string } export type RpcMessage = + | { + type: "wallet_requestAccounts" + params?: RequestAccountsParameters + result: string[] + } | { type: "wallet_watchAsset" params: WatchAssetParameters @@ -68,9 +217,29 @@ export type RpcMessage = } | { type: "wallet_switchStarknetChain" - params: SwitchStarknetChainParameter + params: SwitchStarknetChainParameters result: boolean } + | { + type: "starknet_addInvokeTransaction" + params: AddInvokeTransactionParameters + result: AddInvokeTransactionResult + } + | { + type: "starknet_addDeclareTransaction" + params: AddDeclareTransactionParameters + result: AddDeclareTransactionResult + } + | { + type: "starknet_addDeployAccountTransaction" + params: AddDeployAccountTransactionParameters + result: AddDeployAccountTransactionResult + } + | { + type: "starknet_signTypedData" + params: TypedData + result: string[] + } export interface IStarknetWindowObject { id: string @@ -80,7 +249,6 @@ export interface IStarknetWindowObject { request: ( call: Omit, ) => Promise - enable: (options?: { starknetVersion?: "v4" | "v5" }) => Promise isPreauthorized: () => Promise on: ( event: E["type"], @@ -90,18 +258,15 @@ export interface IStarknetWindowObject { event: E["type"], handleEvent: E["handler"], ) => void - account?: AccountInterface | AccountInterfaceV4 - provider?: ProviderInterface | ProviderInterfaceV4 selectedAddress?: string chainId?: string + isConnected: boolean } export interface ConnectedStarknetWindowObject extends IStarknetWindowObject { - isConnected: true - account: AccountInterface | AccountInterfaceV4 - provider: ProviderInterface | ProviderInterfaceV4 selectedAddress: string chainId: string + isConnected: true } export interface DisconnectedStarknetWindowObject diff --git a/packages/core/src/__test__/wallet.mock.ts b/packages/core/src/__test__/wallet.mock.ts index 5f2a14c..ec9ac09 100644 --- a/packages/core/src/__test__/wallet.mock.ts +++ b/packages/core/src/__test__/wallet.mock.ts @@ -39,7 +39,7 @@ export function makePreAuthorized(isPreauthorized: boolean) { export function makeConnected(isConnected: boolean) { return (wallet: WalletMock) => ({ ...makePreAuthorized(true)(wallet), - enable: async () => [], + request: async () => [], isConnected, }) } diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 16241b9..4dba72f 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -1,5 +1,6 @@ -import { +import type { ConnectedStarknetWindowObject, + RequestAccountsParameters, StarknetWindowObject, } from "./StarknetWindowObject" import discovery, { WalletProvider } from "./discovery" @@ -17,11 +18,18 @@ export type { NetworkChangeEventHandler, RpcMessage, StarknetWindowObject, - SwitchStarknetChainParameter, + SwitchStarknetChainParameters, WalletEvents, WatchAssetParameters, DisconnectedStarknetWindowObject, IStarknetWindowObject, + RequestAccountsParameters, + AddDeclareTransactionParameters, + AddDeclareTransactionResult, + AddDeployAccountTransactionParameters, + AddDeployAccountTransactionResult, + AddInvokeTransactionParameters, + AddInvokeTransactionResult, } from "./StarknetWindowObject" export type { WalletProvider } from "./discovery" @@ -59,9 +67,7 @@ interface GetStarknetResult { getLastConnectedWallet: () => Promise // Returns the last wallet connected when it's still connected enable: ( wallet: StarknetWindowObject, - options?: { - starknetVersion?: "v4" | "v5" - }, + options?: RequestAccountsParameters, ) => Promise // Connects to a wallet disconnect: (options?: DisconnectOptions) => Promise // Disconnects from a wallet } @@ -121,7 +127,7 @@ export function getStarknet( return firstPreAuthorizedWallet }, enable: async (wallet, options) => { - await wallet.enable(options ?? { starknetVersion: "v5" }) + await wallet.request({ type: "wallet_requestAccounts", params: options }) if (!wallet.isConnected) { throw new Error("Failed to connect to wallet") } diff --git a/packages/core/src/wallet/isWalletObject.ts b/packages/core/src/wallet/isWalletObject.ts index 73034da..92696c8 100644 --- a/packages/core/src/wallet/isWalletObject.ts +++ b/packages/core/src/wallet/isWalletObject.ts @@ -7,7 +7,6 @@ export const isWalletObj = (wallet: any): boolean => { "request", "isConnected", "provider", - "enable", "isPreauthorized", "on", "off", diff --git a/packages/ui/src/main.ts b/packages/ui/src/main.ts index 8b236a0..45085e2 100644 --- a/packages/ui/src/main.ts +++ b/packages/ui/src/main.ts @@ -3,6 +3,7 @@ import Bowser from "bowser" import sn, { type DisconnectOptions, type GetWalletOptions, + type RequestAccountsParameters, type StarknetWindowObject, } from "get-starknet-core" @@ -39,11 +40,14 @@ export interface ConnectOptions extends GetWalletOptions { storeVersion?: StoreVersion } -const enableWithVersion = async (wallet: StarknetWindowObject | null) => { +const enableWithVersion = async ( + wallet: StarknetWindowObject | null, + options?: RequestAccountsParameters, +) => { if (!wallet) { return null } - return sn.enable(wallet, { starknetVersion: "v5" }).catch(() => null) + return sn.enable(wallet, options).catch(() => null) } export const connect = async ({ @@ -64,7 +68,7 @@ export const connect = async ({ // return `wallet` even if it's null/undefined since we aren't allowed // to show any "connect" related UI - return enableWithVersion(wallet) + return enableWithVersion(wallet, { silentMode: true }) } const installedWallets = await sn.getAvailableWallets(restOptions) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f79396e..77b7de7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,12 +72,6 @@ importers: happy-dom: specifier: ^6.0.4 version: 6.0.4 - starknet: - specifier: ^5.18.0 - version: 5.18.0 - starknet4: - specifier: npm:starknet@4.22.0 - version: /starknet@4.22.0 typescript: specifier: ^4.6.4 version: 4.6.4 @@ -86,7 +80,7 @@ importers: version: 3.0.0 vite-plugin-dts: specifier: ^1.4.0 - version: 1.4.0(@types/node@20.3.1)(vite@3.0.0) + version: 1.4.0(vite@3.0.0) vitest: specifier: ^0.19.1 version: 0.19.1(c8@7.12.0)(happy-dom@6.0.4) @@ -878,16 +872,6 @@ packages: dev: true optional: true - /@ethersproject/bytes@5.7.0: - resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} - dependencies: - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/logger@5.7.0: - resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} - dev: true - /@istanbuljs/schema@0.1.3: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} @@ -959,6 +943,16 @@ packages: read-yaml-file: 1.1.0 dev: true + /@microsoft/api-extractor-model@7.27.3: + resolution: {integrity: sha512-fSFvw7otYHduOkyshjTbapKKgwF8bgquVHvgF8VgeKtMYvqXkoaj7W6VcM7PNY7E2bbblhUgC4XNdqZLD4SJGw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.59.4 + transitivePeerDependencies: + - '@types/node' + dev: true + /@microsoft/api-extractor-model@7.27.3(@types/node@20.3.1): resolution: {integrity: sha512-fSFvw7otYHduOkyshjTbapKKgwF8bgquVHvgF8VgeKtMYvqXkoaj7W6VcM7PNY7E2bbblhUgC4XNdqZLD4SJGw==} dependencies: @@ -969,6 +963,26 @@ packages: - '@types/node' dev: true + /@microsoft/api-extractor@7.36.0: + resolution: {integrity: sha512-P+kYgJFDXIr+UNzhRMhlpM/dderi6ab4lxn35vdhfAIMPtGCSXIJxrrtpTOQmQW8CZtmoZX06LYoUsKCc1zjow==} + hasBin: true + dependencies: + '@microsoft/api-extractor-model': 7.27.3 + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.59.4 + '@rushstack/rig-package': 0.4.0 + '@rushstack/ts-command-line': 4.15.1 + colors: 1.2.5 + lodash: 4.17.21 + resolve: 1.22.2 + semver: 7.3.8 + source-map: 0.6.1 + typescript: 5.0.4 + transitivePeerDependencies: + - '@types/node' + dev: true + /@microsoft/api-extractor@7.36.0(@types/node@20.3.1): resolution: {integrity: sha512-P+kYgJFDXIr+UNzhRMhlpM/dderi6ab4lxn35vdhfAIMPtGCSXIJxrrtpTOQmQW8CZtmoZX06LYoUsKCc1zjow==} hasBin: true @@ -1002,29 +1016,6 @@ packages: resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} dev: true - /@noble/curves@1.0.0: - resolution: {integrity: sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==} - dependencies: - '@noble/hashes': 1.3.0 - dev: true - - /@noble/hashes@1.2.0: - resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} - dev: true - - /@noble/hashes@1.3.0: - resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} - dev: true - - /@noble/hashes@1.3.1: - resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} - engines: {node: '>= 16'} - dev: true - - /@noble/secp256k1@1.7.1: - resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} - dev: true - /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1054,6 +1045,23 @@ packages: picomatch: 2.3.1 dev: true + /@rushstack/node-core-library@3.59.4: + resolution: {integrity: sha512-YAKJDC6Mz/KA1D7bvB88WaRX3knt/ZuLzkRu5G9QADGSjLtvTWzCNCytRF2PCSaaHOZaZsWul4F1KQdgFgUDqA==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.2 + semver: 7.3.8 + z-schema: 5.0.5 + dev: true + /@rushstack/node-core-library@3.59.4(@types/node@20.3.1): resolution: {integrity: sha512-YAKJDC6Mz/KA1D7bvB88WaRX3knt/ZuLzkRu5G9QADGSjLtvTWzCNCytRF2PCSaaHOZaZsWul4F1KQdgFgUDqA==} peerDependencies: @@ -1088,25 +1096,6 @@ packages: string-argv: 0.3.2 dev: true - /@scure/base@1.1.1: - resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} - dev: true - - /@scure/bip32@1.1.5: - resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} - dependencies: - '@noble/hashes': 1.2.0 - '@noble/secp256k1': 1.7.1 - '@scure/base': 1.1.1 - dev: true - - /@scure/bip39@1.1.1: - resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} - dependencies: - '@noble/hashes': 1.2.0 - '@scure/base': 1.1.1 - dev: true - /@sveltejs/vite-plugin-svelte@1.0.1(svelte@3.49.0)(vite@3.0.0): resolution: {integrity: sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==} engines: {node: ^14.18.0 || >= 16} @@ -1517,23 +1506,11 @@ packages: is-windows: 1.0.2 dev: true - /bignumber.js@9.1.1: - resolution: {integrity: sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==} - dev: true - /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} dev: true - /bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: true - - /bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - dev: true - /bowser@2.11.0: resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} dev: false @@ -1564,10 +1541,6 @@ packages: wcwidth: 1.0.1 dev: true - /brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - dev: true - /browserslist@4.21.9: resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -1805,6 +1778,7 @@ packages: /commander@9.5.0: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} + requiresBuild: true dev: true /compare-func@2.0.0: @@ -2068,18 +2042,6 @@ packages: resolution: {integrity: sha512-5Gvm09UZTQRaWrimRtWRO5rvaX6Kpk5WHAPKDa7A4Gj6NIPuJ8w8WNpnxCXdd+CJJt6RBU6tUw0KyULoW6XuHw==} dev: true - /elliptic@6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} - dependencies: - bn.js: 4.12.0 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: true - /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true @@ -2398,15 +2360,6 @@ packages: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} dev: true - /ethereum-cryptography@1.2.0: - resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} - dependencies: - '@noble/hashes': 1.2.0 - '@noble/secp256k1': 1.7.1 - '@scure/bip32': 1.1.5 - '@scure/bip39': 1.1.1 - dev: true - /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -2802,26 +2755,11 @@ packages: function-bind: 1.1.1 dev: true - /hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - dev: true - /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true dev: true - /hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: true - /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true @@ -3132,15 +3070,6 @@ packages: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true - /isomorphic-fetch@3.0.0: - resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} - dependencies: - node-fetch: 2.6.11 - whatwg-fetch: 3.6.2 - transitivePeerDependencies: - - encoding - dev: true - /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} @@ -3195,12 +3124,6 @@ packages: hasBin: true dev: true - /json-bigint@1.0.0: - resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} - dependencies: - bignumber.js: 9.1.1 - dev: true - /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true @@ -3398,10 +3321,6 @@ packages: js-tokens: 4.0.0 dev: false - /lossless-json@2.0.9: - resolution: {integrity: sha512-PUfJ5foxULG1x/dXpSckmt0woBDqyq/WFoI885vEqjGwuP41K2EBYh2IT3zYx9dWqcTLIfXiCE5AjhF1jk9Sbg==} - dev: true - /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} dependencies: @@ -3505,13 +3424,6 @@ packages: engines: {node: '>= 8'} dev: true - /micro-starknet@0.2.3: - resolution: {integrity: sha512-6XBcC+GerlwJSR4iA0VaeXtS2wrayWFcA4PEzrJPMuFmWCaUtuGIq5K/DB5F/XgnL54/zl2Bxo690Lj7mYVA8A==} - dependencies: - '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.1 - dev: true - /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -3547,14 +3459,6 @@ packages: engines: {node: '>=4'} dev: true - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true - - /minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - dev: true - /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -3778,10 +3682,6 @@ packages: engines: {node: '>=6'} dev: true - /pako@2.1.0: - resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} - dev: true - /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -4488,37 +4388,6 @@ packages: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true - /starknet@4.22.0: - resolution: {integrity: sha512-jC9Taxb6a/ht9zmS1LU/DSLfwJKpgCJnE9AktVksc5SE/+jQMpqxsq6fm7PRiqupjiqRC1DOS8N47cj+KaGv4Q==} - dependencies: - '@ethersproject/bytes': 5.7.0 - bn.js: 5.2.1 - elliptic: 6.5.4 - ethereum-cryptography: 1.2.0 - hash.js: 1.1.7 - isomorphic-fetch: 3.0.0 - json-bigint: 1.0.0 - minimalistic-assert: 1.0.1 - pako: 2.1.0 - ts-custom-error: 3.3.1 - url-join: 4.0.1 - transitivePeerDependencies: - - encoding - dev: true - - /starknet@5.18.0: - resolution: {integrity: sha512-2b5+F+kfp8fTBAfBpHNmtjhuljZb3P2JMhubP/KWIJAGXwBAalPklOwEYY7Bb2slkPjfkDH0kPxI4037sQcQ+Q==} - dependencies: - '@noble/curves': 1.0.0 - isomorphic-fetch: 3.0.0 - lossless-json: 2.0.9 - micro-starknet: 0.2.3 - pako: 2.1.0 - url-join: 4.0.1 - transitivePeerDependencies: - - encoding - dev: true - /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} dependencies: @@ -4872,11 +4741,6 @@ packages: engines: {node: '>=8'} dev: true - /ts-custom-error@3.3.1: - resolution: {integrity: sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==} - engines: {node: '>=14.0.0'} - dev: true - /ts-morph@14.0.0: resolution: {integrity: sha512-tO8YQ1dP41fw8GVmeQAdNsD8roZi1JMqB7YwZrqU856DvmG5/710e41q2XauzTYrygH9XmMryaFeLo+kdCziyA==} dependencies: @@ -5023,10 +4887,6 @@ packages: punycode: 2.3.0 dev: true - /url-join@4.0.1: - resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} - dev: true - /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true @@ -5075,6 +4935,25 @@ packages: - supports-color dev: true + /vite-plugin-dts@1.4.0(vite@3.0.0): + resolution: {integrity: sha512-RyDCjQzVxUeDqF+Rl1hQT+t/rKmvfvo04gaGV/l3597FpeIWGKtNF1S4x509Kx1AfHOjLa1JdmjVgnSEIv+lpw==} + engines: {node: '>=12.0.0'} + peerDependencies: + vite: '>=2.4.4' + dependencies: + '@microsoft/api-extractor': 7.36.0 + '@rushstack/node-core-library': 3.59.4 + chalk: 4.1.2 + debug: 4.3.4 + fast-glob: 3.2.12 + fs-extra: 10.1.0 + ts-morph: 14.0.0 + vite: 3.0.0 + transitivePeerDependencies: + - '@types/node' + - supports-color + dev: true + /vite@3.0.0: resolution: {integrity: sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==} engines: {node: '>=14.18.0'} @@ -5168,10 +5047,6 @@ packages: iconv-lite: 0.6.3 dev: true - /whatwg-fetch@3.6.2: - resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} - dev: true - /whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} From 654ee0e8b31ad0b5353e17d031be122e6dd093e3 Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Mon, 2 Oct 2023 19:17:15 +0300 Subject: [PATCH 02/16] chore: export `TypeData` --- packages/core/src/StarknetWindowObject.ts | 2 +- packages/core/src/main.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index e6deaae..65f1416 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -36,7 +36,7 @@ interface StarkNetDomain extends Record { /** * The complete typed data, with all the structs, domain data, primary type of the message, and the message itself. */ -interface TypedData { +export interface TypedData { types: Record primaryType: string domain: StarkNetDomain diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 4dba72f..517808c 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -30,6 +30,7 @@ export type { AddDeployAccountTransactionResult, AddInvokeTransactionParameters, AddInvokeTransactionResult, + TypedData, } from "./StarknetWindowObject" export type { WalletProvider } from "./discovery" From db5fae32d02c951f01512567a06eeeef318214c5 Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Mon, 2 Oct 2023 20:46:32 +0300 Subject: [PATCH 03/16] chore: reverting from raw `calldata` to calls it will be complicated for wallets to decode FELT-encoded entrypoints. it's doable but slow, and slightly shifting from a pure RPC-schema approach seems reasonable in this use case. --- packages/core/src/StarknetWindowObject.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 65f1416..edcedfd 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -1,5 +1,11 @@ type FELT = string +type Call = { + contract_address: FELT + entrypoint: string + calldata?: FELT[] +} + type SIERRA_ENTRY_POINT = { selector: FELT function_idx: number @@ -63,10 +69,9 @@ export type WalletEvents = */ export interface AddInvokeTransactionParameters { /** - * The data expected by the account's `execute` function (in most use-cases, - * this includes the called contract address and a function selector) + * Calls to invoke by the account */ - calldata: FELT[] + calls: Call[] } export interface AddInvokeTransactionResult { /** From d152cce823acb015692731eadf158c78c88734eb Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Wed, 4 Oct 2023 21:16:50 +0300 Subject: [PATCH 04/16] chore: rename `StarkNet` to `Starknet` --- packages/core/src/StarknetWindowObject.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index edcedfd..9c659a8 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -11,7 +11,7 @@ type SIERRA_ENTRY_POINT = { function_idx: number } -type StarkNetMerkleType = { +type StarknetMerkleType = { name: string type: "merkletree" contains: string @@ -23,17 +23,17 @@ type StarkNetMerkleType = { * Note that the `uint` and `int` aliases like in Solidity, and fixed point numbers are not supported by the EIP-712 * standard. */ -type StarkNetType = +type StarknetType = | { name: string type: string } - | StarkNetMerkleType + | StarknetMerkleType /** * The EIP712 domain struct. Any of these fields are optional, but it must contain at least one field. */ -interface StarkNetDomain extends Record { +interface StarknetDomain extends Record { name?: string version?: string chainId?: string | number @@ -43,9 +43,9 @@ interface StarkNetDomain extends Record { * The complete typed data, with all the structs, domain data, primary type of the message, and the message itself. */ export interface TypedData { - types: Record + types: Record primaryType: string - domain: StarkNetDomain + domain: StarknetDomain message: Record } @@ -171,7 +171,7 @@ export interface RequestAccountsParameters { export interface WatchAssetParameters { type: "ERC20" // The asset's interface, e.g. 'ERC20' options: { - address: string // The hexadecimal StarkNet address of the token contract + address: string // The hexadecimal Starknet address of the token contract symbol?: string // A ticker symbol or shorthand, up to 5 alphanumerical characters decimals?: number // The number of asset decimals image?: string // A string url of the token logo @@ -192,7 +192,7 @@ export interface AddStarknetChainParameters { blockExplorerUrls?: string[] nativeCurrency?: { - address: string // Not part of the standard, but required by StarkNet as it can work with any ERC20 token as the fee token + address: string // Not part of the standard, but required by Starknet as it can work with any ERC20 token as the fee token name: string symbol: string // 2-6 characters long decimals: number From d8d479bb8e6d41679085abda2a5d011d33781809 Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Thu, 14 Dec 2023 15:14:57 +0200 Subject: [PATCH 05/16] chore: removed `isPreauthorized`, `selectedAddress`, `chainId`, `isConnected` --- packages/core/src/StarknetWindowObject.ts | 48 +++++------ packages/core/src/__test__/main.test.ts | 30 +++---- packages/core/src/__test__/storage.test.ts | 32 +++---- packages/core/src/__test__/wallet.mock.ts | 65 ++++++++++----- packages/core/src/main.ts | 97 +++++++++------------- packages/core/src/types.ts | 42 ++++++++++ packages/core/src/utils.ts | 9 +- packages/core/src/wallet/filter.ts | 15 +++- packages/core/src/wallet/isWalletObject.ts | 3 - packages/ui/src/main.ts | 10 +-- packages/ui/src/modal/Modal.svelte | 4 +- packages/ui/src/modal/index.ts | 20 ++--- 12 files changed, 212 insertions(+), 163 deletions(-) create mode 100644 packages/core/src/types.ts diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 9c659a8..dd0dc7c 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -1,3 +1,12 @@ +export enum StarknetChainId { + SN_MAIN = "0x534e5f4d41494e", + SN_GOERLI = "0x534e5f474f45524c49", +} + +export enum Permission { + Accounts = "accounts", +} + type FELT = string type Call = { @@ -51,7 +60,10 @@ export interface TypedData { export type AccountChangeEventHandler = (accounts?: string[]) => void -export type NetworkChangeEventHandler = (network?: string) => void +export type NetworkChangeEventHandler = ( + chainId?: StarknetChainId, + accounts?: string[], +) => void export type WalletEvents = | { @@ -205,6 +217,11 @@ export interface SwitchStarknetChainParameters { } export type RpcMessage = + | { + type: "wallet_getPermissions" + params: never + result: Permission[] + } | { type: "wallet_requestAccounts" params?: RequestAccountsParameters @@ -225,6 +242,11 @@ export type RpcMessage = params: SwitchStarknetChainParameters result: boolean } + | { + type: "wallet_requestChainId" + params: never + result: StarknetChainId // returns the chain ID of the current network + } | { type: "starknet_addInvokeTransaction" params: AddInvokeTransactionParameters @@ -246,7 +268,7 @@ export type RpcMessage = result: string[] } -export interface IStarknetWindowObject { +export interface StarknetWindowObject { id: string name: string version: string @@ -254,7 +276,6 @@ export interface IStarknetWindowObject { request: ( call: Omit, ) => Promise - isPreauthorized: () => Promise on: ( event: E["type"], handleEvent: E["handler"], @@ -263,31 +284,10 @@ export interface IStarknetWindowObject { event: E["type"], handleEvent: E["handler"], ) => void - selectedAddress?: string - chainId?: string - isConnected: boolean -} - -export interface ConnectedStarknetWindowObject extends IStarknetWindowObject { - selectedAddress: string - chainId: string - isConnected: true } -export interface DisconnectedStarknetWindowObject - extends IStarknetWindowObject { - isConnected: false -} - -export type StarknetWindowObject = - | ConnectedStarknetWindowObject - | DisconnectedStarknetWindowObject - declare global { interface Window { - starknet?: StarknetWindowObject - starknet_braavos?: StarknetWindowObject - starknet_argentX?: StarknetWindowObject [key: `starknet_${string}`]: StarknetWindowObject | undefined } } diff --git a/packages/core/src/__test__/main.test.ts b/packages/core/src/__test__/main.test.ts index 50d3830..a98faf9 100644 --- a/packages/core/src/__test__/main.test.ts +++ b/packages/core/src/__test__/main.test.ts @@ -3,9 +3,9 @@ import { mockStorageFunction } from "./storage.mock" import { ArgentXMock, BraavosMock, + makeAuthorized, UnknownWalletAMock, UnknownWalletBMock, - makePreAuthorized, } from "./wallet.mock" import { describe, expect, it } from "vitest" @@ -105,25 +105,25 @@ describe("getAvailableWallets()", () => { }) }) -describe("getPreAuthorizedWallets()", () => { - it("should return all preauthorized wallets", async () => { +describe("getAuthorizedWallets()", () => { + it("should return all authorized wallets", async () => { const sn = getWallet({ - "starknet-argent": makePreAuthorized(true)(ArgentXMock), - "starknet-braavos": makePreAuthorized(true)(BraavosMock), + "starknet-argent": makeAuthorized(true)(ArgentXMock), + "starknet-braavos": makeAuthorized(true)(BraavosMock), }) - const preauthorizedWallets = await sn.getPreAuthorizedWallets() - expect(preauthorizedWallets.length).toBe(2) - expect(preauthorizedWallets.map((w) => w.id)).contains(ArgentXMock.id) - expect(preauthorizedWallets.map((w) => w.id)).contains(BraavosMock.id) + const authorizedWallets = await sn.getAuthorizedWallets() + expect(authorizedWallets.length).toBe(2) + expect(authorizedWallets.map((w) => w.id)).contains(ArgentXMock.id) + expect(authorizedWallets.map((w) => w.id)).contains(BraavosMock.id) }) - it("should return one preauthorized wallet", async () => { + it("should return one authorized wallet", async () => { const sn = getWallet({ - "starknet-argent": makePreAuthorized(true)(ArgentXMock), - "starknet-braavos": makePreAuthorized(false)(BraavosMock), + "starknet-argent": makeAuthorized(true)(ArgentXMock), + "starknet-braavos": makeAuthorized(false)(BraavosMock), }) - const preauthorizedWallets = await sn.getPreAuthorizedWallets() - expect(preauthorizedWallets.length).toBe(1) - expect(preauthorizedWallets.map((w) => w.id)).contains(ArgentXMock.id) + const authorizedWallets = await sn.getAuthorizedWallets() + expect(authorizedWallets.length).toBe(1) + expect(authorizedWallets.map((w) => w.id)).contains(ArgentXMock.id) }) }) diff --git a/packages/core/src/__test__/storage.test.ts b/packages/core/src/__test__/storage.test.ts index def4c4b..2d5727e 100644 --- a/packages/core/src/__test__/storage.test.ts +++ b/packages/core/src/__test__/storage.test.ts @@ -3,10 +3,10 @@ import { mockStorageFunction } from "./storage.mock" import { ArgentXMock, BraavosMock, + makeAuthorized, + makeConnected, UnknownWalletAMock, UnknownWalletBMock, - makeConnected, - makePreAuthorized, } from "./wallet.mock" import { describe, expect, it } from "vitest" @@ -24,8 +24,8 @@ function getWallet( describe("getLastConnectedWallet()", () => { it("should return null if no last wallet set", async () => { const sn = getWallet({ - "starknet-walletA": makePreAuthorized(false)(UnknownWalletAMock), - "starknet-walletB": makePreAuthorized(false)(UnknownWalletBMock), + "starknet-walletA": makeAuthorized(false)(UnknownWalletAMock), + "starknet-walletB": makeAuthorized(false)(UnknownWalletBMock), }) const lastConnectedWallet = await sn.getLastConnectedWallet() expect(lastConnectedWallet).toBe(null) @@ -33,8 +33,8 @@ describe("getLastConnectedWallet()", () => { it("should return null if the last connected wallet is not available", async () => { const sn = getWallet( { - "starknet-walletA": makePreAuthorized(false)(UnknownWalletAMock), - "starknet-walletB": makePreAuthorized(false)(UnknownWalletBMock), + "starknet-walletA": makeAuthorized(false)(UnknownWalletAMock), + "starknet-walletB": makeAuthorized(false)(UnknownWalletBMock), }, mockStorageFunction({ "gsw-last": "braavos", @@ -46,8 +46,8 @@ describe("getLastConnectedWallet()", () => { it("should not return the last connected wallet if not preauthorized", async () => { const sn = getWallet( { - "starknet-argentX": makePreAuthorized(false)(ArgentXMock), - "starknet-braavos": makePreAuthorized(false)(BraavosMock), + "starknet-argentX": makeAuthorized(false)(ArgentXMock), + "starknet-braavos": makeAuthorized(false)(BraavosMock), }, mockStorageFunction({ "gsw-last": "braavos", @@ -59,8 +59,8 @@ describe("getLastConnectedWallet()", () => { it("should return the last connected wallet if still preauthorized", async () => { const sn = getWallet( { - "starknet-argentX": makePreAuthorized(false)(ArgentXMock), - "starknet-braavos": makePreAuthorized(true)(BraavosMock), + "starknet-argentX": makeAuthorized(false)(ArgentXMock), + "starknet-braavos": makeAuthorized(true)(BraavosMock), }, mockStorageFunction({ "gsw-last": "braavos", @@ -72,8 +72,8 @@ describe("getLastConnectedWallet()", () => { it("should return the last connected wallet when last is available", async () => { const sn = getWallet( { - "starknet-argentX": makePreAuthorized(true)(ArgentXMock), - "starknet-braavos": makePreAuthorized(true)(BraavosMock), + "starknet-argentX": makeAuthorized(true)(ArgentXMock), + "starknet-braavos": makeAuthorized(true)(BraavosMock), }, mockStorageFunction({ "gsw-last": "braavos" }), ) @@ -106,8 +106,8 @@ describe("getLastConnectedWallet()", () => { it("should default disable", async () => { const sn = getWallet( { - "starknet-argentX": makePreAuthorized(true)(ArgentXMock), - "starknet-braavos": makePreAuthorized(true)(BraavosMock), + "starknet-argentX": makeAuthorized(true)(ArgentXMock), + "starknet-braavos": makeAuthorized(true)(BraavosMock), }, mockStorageFunction({ "gsw-last": "braavos", @@ -123,8 +123,8 @@ describe("getLastConnectedWallet()", () => { it("should disable with clearLastWallet", async () => { const sn = getWallet( { - "starknet-argentX": makePreAuthorized(true)(ArgentXMock), - "starknet-braavos": makePreAuthorized(true)(BraavosMock), + "starknet-argentX": makeAuthorized(true)(ArgentXMock), + "starknet-braavos": makeAuthorized(true)(BraavosMock), }, mockStorageFunction({ "gsw-last": "braavos", diff --git a/packages/core/src/__test__/wallet.mock.ts b/packages/core/src/__test__/wallet.mock.ts index ec9ac09..4a54248 100644 --- a/packages/core/src/__test__/wallet.mock.ts +++ b/packages/core/src/__test__/wallet.mock.ts @@ -1,45 +1,72 @@ -import type { StarknetWindowObject } from "../StarknetWindowObject" +import { Permission, StarknetWindowObject } from "../StarknetWindowObject" import wallets from "../discovery" -type WalletMock = Pick< - StarknetWindowObject, - "id" | "name" | "icon" | "isPreauthorized" -> +type WalletMock = Pick export const UnknownWalletAMock: WalletMock = { id: "wallet-a", name: "Wallet A", icon: "https://avatars.dicebear.com/api/initials/Wallet%20A.svg", - isPreauthorized: async () => false, + request: async () => false, } export const UnknownWalletBMock: WalletMock = { id: "wallet-b", name: "Wallet B", icon: "https://avatars.dicebear.com/api/initials/Wallet%20B.svg", - isPreauthorized: async () => false, + request: async () => false, } export const ArgentXMock: WalletMock = { ...wallets.find((w) => w.id === "argentX")!, - isPreauthorized: async () => false, + request: async (request) => { + switch (request.type) { + case "wallet_getPermissions": + return [] + default: + return undefined as any + } + }, } export const BraavosMock: WalletMock = { ...wallets.find((w) => w.id === "braavos")!, - isPreauthorized: async () => false, + request: async (request) => { + switch (request.type) { + case "wallet_getPermissions": + return [] + default: + return undefined as any + } + }, } -export function makePreAuthorized(isPreauthorized: boolean) { - return (wallet: WalletMock) => ({ - ...wallet, - isPreauthorized: async () => isPreauthorized, - }) +export function makeAuthorized(authorized: boolean) { + return (wallet: WalletMock) => + ({ + ...wallet, + request: async (request) => { + switch (request.type) { + case "wallet_getPermissions": + return authorized ? [Permission.Accounts] : [] + default: + return wallet.request(request) + } + }, + } as WalletMock) } export function makeConnected(isConnected: boolean) { - return (wallet: WalletMock) => ({ - ...makePreAuthorized(true)(wallet), - request: async () => [], - isConnected, - }) + return (wallet: WalletMock) => { + return { + ...makeAuthorized(true)(wallet), + request: async ({ type }) => { + switch (type) { + case "wallet_getPermissions": + return isConnected ? [Permission.Accounts] : [] + default: + return [] + } + }, + } as WalletMock + } } diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 517808c..138c9a1 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -1,44 +1,42 @@ -import type { - ConnectedStarknetWindowObject, - RequestAccountsParameters, - StarknetWindowObject, -} from "./StarknetWindowObject" -import discovery, { WalletProvider } from "./discovery" -import { IStorageWrapper, LocalStorageWrapper } from "./localStorageStore" +import { Permission, type StarknetWindowObject } from "./StarknetWindowObject" +import discovery, { type WalletProvider } from "./discovery" +import { LocalStorageWrapper } from "./localStorageStore" +import type { GetStarknetOptions, GetStarknetResult } from "./types" import { pipe } from "./utils" -import { FilterList, filterBy, filterByPreAuthorized } from "./wallet/filter" +import { filterBy, filterByAuthorized } from "./wallet/filter" import { isWalletObj } from "./wallet/isWalletObject" import { scanObjectForWallets } from "./wallet/scan" -import { Sort, sortBy } from "./wallet/sort" +import { sortBy } from "./wallet/sort" export type { AccountChangeEventHandler, - AddStarknetChainParameters, - ConnectedStarknetWindowObject, - NetworkChangeEventHandler, - RpcMessage, - StarknetWindowObject, - SwitchStarknetChainParameters, - WalletEvents, - WatchAssetParameters, - DisconnectedStarknetWindowObject, - IStarknetWindowObject, - RequestAccountsParameters, AddDeclareTransactionParameters, AddDeclareTransactionResult, AddDeployAccountTransactionParameters, AddDeployAccountTransactionResult, AddInvokeTransactionParameters, AddInvokeTransactionResult, + AddStarknetChainParameters, + NetworkChangeEventHandler, + RequestAccountsParameters, + RpcMessage, + StarknetChainId, + StarknetWindowObject, + SwitchStarknetChainParameters, TypedData, + WalletEvents, + WatchAssetParameters, } from "./StarknetWindowObject" -export type { WalletProvider } from "./discovery" -export interface GetStarknetOptions { - windowObject: Record - isWalletObject: (wallet: any) => boolean - storageFactoryImplementation: (name: string) => IStorageWrapper -} +export { Permission } from "./StarknetWindowObject" + +export type { + DisconnectOptions, + GetStarknetOptions, + GetStarknetResult, + GetWalletOptions, + WalletProvider, +} from "./types" const ssrSafeWindow = typeof window !== "undefined" ? window : {} @@ -48,31 +46,6 @@ const defaultOptions: GetStarknetOptions = { storageFactoryImplementation: (name: string) => new LocalStorageWrapper(name), } -export interface GetWalletOptions { - sort?: Sort - include?: FilterList - exclude?: FilterList -} - -export interface DisconnectOptions { - clearLastWallet?: boolean -} -interface GetStarknetResult { - getAvailableWallets: ( - options?: GetWalletOptions, - ) => Promise // Returns all wallets available in the window object - getPreAuthorizedWallets: ( - options?: GetWalletOptions, - ) => Promise // Returns only preauthorized wallets available in the window object - getDiscoveryWallets: (options?: GetWalletOptions) => Promise // Returns all wallets in existence (from discovery file) - getLastConnectedWallet: () => Promise // Returns the last wallet connected when it's still connected - enable: ( - wallet: StarknetWindowObject, - options?: RequestAccountsParameters, - ) => Promise // Connects to a wallet - disconnect: (options?: DisconnectOptions) => Promise // Disconnects from a wallet -} - export function getStarknet( options: Partial = {}, ): GetStarknetResult { @@ -93,13 +66,13 @@ export function getStarknet( (_) => sortBy(_, options.sort), )(availableWallets) }, - getPreAuthorizedWallets: async (options = {}) => { + getAuthorizedWallets: async (options = {}) => { const availableWallets = scanObjectForWallets( windowObject, isWalletObject, ) return pipe( - (_) => filterByPreAuthorized(_), + (_) => filterByAuthorized(_), (_) => filterBy(_, options), (_) => sortBy(_, options.sort), )(availableWallets) @@ -116,20 +89,28 @@ export function getStarknet( const lastConnectedWallet = allWallets.find( (w) => w.id === lastConnectedWalletId, ) - const [firstPreAuthorizedWallet] = await filterByPreAuthorized( + const [firstAuthorizedWallet] = await filterByAuthorized( lastConnectedWallet ? [lastConnectedWallet] : [], ) - if (!firstPreAuthorizedWallet) { + if (!firstAuthorizedWallet) { lastConnectedStore.delete() return null } - return firstPreAuthorizedWallet + return firstAuthorizedWallet }, enable: async (wallet, options) => { - await wallet.request({ type: "wallet_requestAccounts", params: options }) - if (!wallet.isConnected) { + await wallet.request({ + type: "wallet_requestAccounts", + params: options, + }) + + // check for permissions + const permissions = (await wallet.request({ + type: "wallet_getPermissions", + })) as Permission[] + if (!permissions?.includes(Permission.Accounts)) { throw new Error("Failed to connect to wallet") } lastConnectedStore.set(wallet.id) diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts new file mode 100644 index 0000000..7c4f935 --- /dev/null +++ b/packages/core/src/types.ts @@ -0,0 +1,42 @@ +import { IStorageWrapper } from "./localStorageStore" +import { Sort } from "./wallet/sort" +import { FilterList } from "./wallet/filter" +import { + RequestAccountsParameters, + StarknetWindowObject, +} from "./StarknetWindowObject" +import { WalletProvider } from "./discovery" + +export type { WalletProvider } from "./discovery" + +export interface GetStarknetOptions { + windowObject: Record + isWalletObject: (wallet: any) => boolean + storageFactoryImplementation: (name: string) => IStorageWrapper +} + +export interface GetWalletOptions { + sort?: Sort + include?: FilterList + exclude?: FilterList +} + +export interface DisconnectOptions { + clearLastWallet?: boolean +} + +export interface GetStarknetResult { + getAvailableWallets: ( + options?: GetWalletOptions, + ) => Promise // Returns all wallets available in the window object + getAuthorizedWallets: ( + options?: GetWalletOptions, + ) => Promise // Returns only preauthorized wallets available in the window object + getDiscoveryWallets: (options?: GetWalletOptions) => Promise // Returns all wallets in existence (from discovery file) + getLastConnectedWallet: () => Promise // Returns the last wallet connected when it's still connected + enable: ( + wallet: StarknetWindowObject, + options?: RequestAccountsParameters, + ) => Promise // Connects to a wallet + disconnect: (options?: DisconnectOptions) => Promise // Disconnects from a wallet +} diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index e4555dd..6f159e2 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -13,8 +13,7 @@ export const shuffle = (arr: T): T => { } type AllowPromise = Promise | T -export function pipe( - ...fns: Array<(arg: T) => AllowPromise> -): (arg: T) => Promise { - return (arg: T) => fns.reduce((acc, fn) => acc.then(fn), Promise.resolve(arg)) -} +export const pipe = + (...fns: Array<(arg: T) => AllowPromise>): ((arg: T) => Promise) => + (arg: T) => + fns.reduce>((acc, fn) => acc.then(fn), Promise.resolve(arg)) diff --git a/packages/core/src/wallet/filter.ts b/packages/core/src/wallet/filter.ts index 8111bbb..d4460d4 100644 --- a/packages/core/src/wallet/filter.ts +++ b/packages/core/src/wallet/filter.ts @@ -1,5 +1,5 @@ -import { StarknetWindowObject } from "../StarknetWindowObject" -import { WalletProvider } from "../discovery" +import { Permission, type StarknetWindowObject } from "../StarknetWindowObject" +import type { WalletProvider } from "../discovery" export type FilterList = string[] interface FilterByOptions { @@ -28,11 +28,18 @@ export function filterBy( * filters given wallets array, return only preAuthorized instances * @param wallets */ -export const filterByPreAuthorized = async ( +export const filterByAuthorized = async ( wallets: StarknetWindowObject[], ): Promise => { const preAuthResponses = await Promise.all( - wallets.map((w) => w.isPreauthorized().catch(() => false)), + wallets.map((w) => + w + .request({ type: "wallet_getPermissions" }) + .then((result) => + (result as Permission[])?.includes(Permission.Accounts), + ) + .catch(() => false), + ), ) return wallets.filter((_, i) => preAuthResponses[i]) } diff --git a/packages/core/src/wallet/isWalletObject.ts b/packages/core/src/wallet/isWalletObject.ts index 92696c8..471db3b 100644 --- a/packages/core/src/wallet/isWalletObject.ts +++ b/packages/core/src/wallet/isWalletObject.ts @@ -5,9 +5,6 @@ export const isWalletObj = (wallet: any): boolean => { [ // wallet's must have methods/members, see IStarknetWindowObject "request", - "isConnected", - "provider", - "isPreauthorized", "on", "off", "version", diff --git a/packages/ui/src/main.ts b/packages/ui/src/main.ts index 45085e2..65f130a 100644 --- a/packages/ui/src/main.ts +++ b/packages/ui/src/main.ts @@ -56,15 +56,15 @@ export const connect = async ({ modalTheme, ...restOptions }: ConnectOptions = {}): Promise => { - const preAuthorizedWallets = await sn.getPreAuthorizedWallets({ + const authorizedWallets = await sn.getAuthorizedWallets({ ...restOptions, }) const lastWallet = await sn.getLastConnectedWallet() if (modalMode === "neverAsk") { const wallet = - preAuthorizedWallets.find((w) => w.id === lastWallet?.id) ?? - preAuthorizedWallets[0] // at this point pre-authorized is already sorted + authorizedWallets.find((w) => w.id === lastWallet?.id) ?? + authorizedWallets[0] // at this point authorized is already sorted // return `wallet` even if it's null/undefined since we aren't allowed // to show any "connect" related UI @@ -78,7 +78,7 @@ export const connect = async ({ lastWallet ) { const wallet = - preAuthorizedWallets.find((w) => w.id === lastWallet?.id) ?? + authorizedWallets.find((w) => w.id === lastWallet?.id) ?? (installedWallets.length === 1 ? installedWallets[0] : undefined) if (wallet) { return enableWithVersion(wallet) @@ -97,7 +97,7 @@ export const connect = async ({ return show({ lastWallet, - preAuthorizedWallets, + authorizedWallets, installedWallets, discoveryWallets: discoveryWalletsByStoreVersion, enable: enableWithVersion, diff --git a/packages/ui/src/modal/Modal.svelte b/packages/ui/src/modal/Modal.svelte index ed18584..6cf8ad0 100644 --- a/packages/ui/src/modal/Modal.svelte +++ b/packages/ui/src/modal/Modal.svelte @@ -6,7 +6,7 @@ const ssrSafeWindow = typeof window !== "undefined" ? window : null export let lastWallet: StarknetWindowObject | null = null export let installedWallets: StarknetWindowObject[] = [] - export let preAuthorizedWallets: StarknetWindowObject[] = [] + export let authorizedWallets: StarknetWindowObject[] = [] export let discoveryWallets: WalletProviderWithStoreVersion[] = [] export let callback: ( value: StarknetWindowObject | null, @@ -50,7 +50,7 @@ const wallets = [ lastWallet, - ...preAuthorizedWallets, + ...authorizedWallets, ...installedWallets, ].filter(Boolean) diff --git a/packages/ui/src/modal/index.ts b/packages/ui/src/modal/index.ts index b61f292..05a4b2e 100644 --- a/packages/ui/src/modal/index.ts +++ b/packages/ui/src/modal/index.ts @@ -1,9 +1,5 @@ import Modal from "./Modal.svelte" -import type { - ConnectedStarknetWindowObject, - StarknetWindowObject, - WalletProvider, -} from "get-starknet-core" +import type { StarknetWindowObject, WalletProvider } from "get-starknet-core" export interface WalletProviderWithStoreVersion extends Omit { @@ -21,17 +17,17 @@ export default async function show({ discoveryWallets, installedWallets, lastWallet, - preAuthorizedWallets, + authorizedWallets, enable, modalOptions, }: { lastWallet?: StarknetWindowObject installedWallets?: StarknetWindowObject[] - preAuthorizedWallets?: StarknetWindowObject[] + authorizedWallets?: StarknetWindowObject[] discoveryWallets?: WalletProviderWithStoreVersion[] enable?: ( wallet: StarknetWindowObject | null, - ) => Promise + ) => Promise modalOptions?: { theme?: "light" | "dark" | "system" } @@ -39,15 +35,15 @@ export default async function show({ return new Promise((resolve) => { // make sure wallets are not shown twice const fixedWallets = [lastWallet].filter(Boolean) - preAuthorizedWallets = excludeWallets(preAuthorizedWallets, fixedWallets) + authorizedWallets = excludeWallets(authorizedWallets, fixedWallets) installedWallets = excludeWallets(installedWallets, [ ...fixedWallets, - ...preAuthorizedWallets, + ...authorizedWallets, ]) discoveryWallets = excludeWallets(discoveryWallets, [ ...fixedWallets, ...installedWallets, - ...preAuthorizedWallets, + ...authorizedWallets, ]) const modal = new Modal({ @@ -60,7 +56,7 @@ export default async function show({ }, lastWallet, installedWallets, - preAuthorizedWallets, + authorizedWallets, discoveryWallets, theme: modalOptions?.theme === "system" ? null : modalOptions?.theme ?? null, From 9c7209853f07492483ce2cb19c54b4a1c618beda Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Thu, 14 Dec 2023 15:41:49 +0200 Subject: [PATCH 06/16] chore: removed `baseUrl` --- packages/core/src/StarknetWindowObject.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index dd0dc7c..3fb4fbc 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -199,7 +199,6 @@ export interface AddStarknetChainParameters { id: string chainId: string // A 0x-prefixed hexadecimal string chainName: string - baseUrl: string rpcUrls?: string[] blockExplorerUrls?: string[] From 08850bf5d5be37e7e4afbf2a8d002a3785ed625c Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Thu, 14 Dec 2023 15:45:05 +0200 Subject: [PATCH 07/16] chore: support custom dark/light icons --- packages/core/src/StarknetWindowObject.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 3fb4fbc..1828e57 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -271,7 +271,7 @@ export interface StarknetWindowObject { id: string name: string version: string - icon: string + icon: string | { dark: string; light: string } request: ( call: Omit, ) => Promise From b7421b3fffda68a3df6dc8e54e9017cd13f6ffd0 Mon Sep 17 00:00:00 2001 From: avimak Date: Tue, 19 Dec 2023 22:07:21 +0200 Subject: [PATCH 08/16] Update packages/core/src/StarknetWindowObject.ts Co-authored-by: naorye2 <147302071+naorye2@users.noreply.github.com> --- packages/core/src/StarknetWindowObject.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 1828e57..144a919 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -218,7 +218,6 @@ export interface SwitchStarknetChainParameters { export type RpcMessage = | { type: "wallet_getPermissions" - params: never result: Permission[] } | { From e3c4e21939dd7e9a9e995e44fa2ceee7ae1ac962 Mon Sep 17 00:00:00 2001 From: avimak Date: Tue, 19 Dec 2023 22:07:50 +0200 Subject: [PATCH 09/16] Update packages/core/src/StarknetWindowObject.ts Co-authored-by: naorye2 <147302071+naorye2@users.noreply.github.com> --- packages/core/src/StarknetWindowObject.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 144a919..623e654 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -242,7 +242,6 @@ export type RpcMessage = } | { type: "wallet_requestChainId" - params: never result: StarknetChainId // returns the chain ID of the current network } | { From 70d28e2c97cd95370212ab506151175e35ad8dfd Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Tue, 19 Dec 2023 22:13:57 +0200 Subject: [PATCH 10/16] chore: support `wallet_deploymentData` request --- packages/core/src/StarknetWindowObject.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 623e654..234df56 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -215,6 +215,14 @@ export interface SwitchStarknetChainParameters { chainId: string // A 0x-prefixed hexadecimal string } +// see https://community.starknet.io/t/snip-deployment-interface-between-dapps-and-wallets/101923 +export interface GetDeploymentDataResult { + address: FELT + class_hash: FELT + salt: FELT + calldata: FELT[] +} + export type RpcMessage = | { type: "wallet_getPermissions" @@ -244,6 +252,10 @@ export type RpcMessage = type: "wallet_requestChainId" result: StarknetChainId // returns the chain ID of the current network } + | { + type: "wallet_deploymentData" + result: GetDeploymentDataResult + } | { type: "starknet_addInvokeTransaction" params: AddInvokeTransactionParameters From 4c24ad3d7abb2d3956eb048fd5b1032b43b75a9c Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Tue, 19 Dec 2023 22:46:58 +0200 Subject: [PATCH 11/16] chore: added missing fields --- packages/core/src/StarknetWindowObject.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 234df56..33b95ef 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -217,10 +217,12 @@ export interface SwitchStarknetChainParameters { // see https://community.starknet.io/t/snip-deployment-interface-between-dapps-and-wallets/101923 export interface GetDeploymentDataResult { - address: FELT - class_hash: FELT - salt: FELT - calldata: FELT[] + address: FELT // the expected address, used to double-check the returned data + class_hash: FELT // The class hash of the contract to deploy + salt: FELT // The salt used for the computation of the account address + calldata: FELT[] // An array of felts + sigdata?: FELT[] // An optional array of felts to be added in the signature + version: 0 | 1 // Cairo version (an integer) } export type RpcMessage = From e6aa45c8e2a79bbf99b878783289f3382c6b4145 Mon Sep 17 00:00:00 2001 From: Abraham Makovetsky Date: Thu, 21 Dec 2023 15:30:34 +0200 Subject: [PATCH 12/16] chore: added supported-specs request message as-per @amanusk suggestion --- packages/core/src/StarknetWindowObject.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 33b95ef..e692f71 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -278,6 +278,10 @@ export type RpcMessage = params: TypedData result: string[] } + | { + type: "starknet_supportedSpecs" + result: string[] // supported starknet specs' tags (see https://github.com/starkware-libs/starknet-specs) + } export interface StarknetWindowObject { id: string From 0d1f43c92f8b794a5a9cd6723eaf91f94ae0224b Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Tue, 23 Jan 2024 17:11:10 +0000 Subject: [PATCH 13/16] chore: add the export for GetDeploymentDataResult --- packages/core/src/main.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 138c9a1..6533ce0 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -26,6 +26,7 @@ export type { TypedData, WalletEvents, WatchAssetParameters, + GetDeploymentDataResult, } from "./StarknetWindowObject" export { Permission } from "./StarknetWindowObject" From 29e2071de77b5d895333408dafcd4a5673bc1ac7 Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Wed, 31 Jan 2024 16:31:12 +0000 Subject: [PATCH 14/16] feat: enhance RpcMessage and EventListener types (#211) * feat: enhance RpcMessage and EventListener types * chore: export more types --- packages/core/src/StarknetWindowObject.ts | 302 +------------------- packages/core/src/main.ts | 35 ++- packages/core/src/rpcMessage.ts | 325 ++++++++++++++++++++++ packages/core/src/types.ts | 10 +- packages/core/src/wallet/filter.ts | 7 +- packages/core/src/walletEvents.ts | 17 ++ 6 files changed, 381 insertions(+), 315 deletions(-) create mode 100644 packages/core/src/rpcMessage.ts create mode 100644 packages/core/src/walletEvents.ts diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index e692f71..8a83961 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -1,304 +1,20 @@ -export enum StarknetChainId { - SN_MAIN = "0x534e5f4d41494e", - SN_GOERLI = "0x534e5f474f45524c49", -} - -export enum Permission { - Accounts = "accounts", -} - -type FELT = string - -type Call = { - contract_address: FELT - entrypoint: string - calldata?: FELT[] -} - -type SIERRA_ENTRY_POINT = { - selector: FELT - function_idx: number -} - -type StarknetMerkleType = { - name: string - type: "merkletree" - contains: string -} +import { RequestFn } from "./rpcMessage" +import { WalletEventHandlers } from "./walletEvents" -/** - * A single type, as part of a struct. The `type` field can be any of the EIP-712 supported types. - * - * Note that the `uint` and `int` aliases like in Solidity, and fixed point numbers are not supported by the EIP-712 - * standard. - */ -type StarknetType = - | { - name: string - type: string - } - | StarknetMerkleType - -/** - * The EIP712 domain struct. Any of these fields are optional, but it must contain at least one field. - */ -interface StarknetDomain extends Record { - name?: string - version?: string - chainId?: string | number -} - -/** - * The complete typed data, with all the structs, domain data, primary type of the message, and the message itself. - */ -export interface TypedData { - types: Record - primaryType: string - domain: StarknetDomain - message: Record -} - -export type AccountChangeEventHandler = (accounts?: string[]) => void - -export type NetworkChangeEventHandler = ( - chainId?: StarknetChainId, - accounts?: string[], +type WalletEventListener = ( + event: E, + handleEvent: WalletEventHandlers[E], ) => void -export type WalletEvents = - | { - type: "accountsChanged" - handler: AccountChangeEventHandler - } - | { - type: "networkChanged" - handler: NetworkChangeEventHandler - } - -/** - * INVOKE_TXN_V1 - * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json - */ -export interface AddInvokeTransactionParameters { - /** - * Calls to invoke by the account - */ - calls: Call[] -} -export interface AddInvokeTransactionResult { - /** - * The hash of the invoke transaction - */ - transaction_hash: FELT -} - -/** - * BROADCASTED_DECLARE_TXN_V2 - * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json - */ -export interface AddDeclareTransactionParameters { - /** - * The hash of the Cairo assembly resulting from the Sierra compilation - */ - compiled_class_hash: FELT - contract_class: { - /** - * The list of Sierra instructions of which the program consists - */ - sierra_program: FELT[] - /** - * The version of the contract class object. Currently, the Starknet OS supports version 0.1.0 - */ - contract_class_version: string - /** - * Entry points by type - */ - entry_points_by_type: { - CONSTRUCTOR: SIERRA_ENTRY_POINT[] - EXTERNAL: SIERRA_ENTRY_POINT[] - L1_HANDLER: SIERRA_ENTRY_POINT[] - } - /** - * The class ABI, as supplied by the user declaring the class - */ - abi?: string - } -} -export interface AddDeclareTransactionResult { - /** - * The hash of the declare transaction - */ - transaction_hash: FELT - /** - * The hash of the declared class - */ - class_hash: FELT -} - -/** - * DEPLOY_ACCOUNT_TXN_V1 - * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json - */ -export interface AddDeployAccountTransactionParameters { - /** - * The salt for the address of the deployed contract - */ - contract_address_salt: FELT - /** - * The parameters passed to the constructor - */ - constructor_calldata: FELT[] - /** - * The hash of the deployed contract's class - */ - class_hash: FELT -} -export interface AddDeployAccountTransactionResult { - /** - * The hash of the deploy transaction - */ - transaction_hash: FELT - /** - * The address of the new contract - */ - contract_address: FELT -} - -/** - * EIP-1102: - * @see https://eips.ethereum.org/EIPS/eip-1102 - */ -export interface RequestAccountsParameters { - /** - * If true, the wallet will not show the wallet-unlock UI in case of a locked wallet, - * nor the dApp-approve UI in case of a non-allowed dApp. - */ - silentMode?: boolean -} - -/** - * EIP-747: - * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-747.md - */ -export interface WatchAssetParameters { - type: "ERC20" // The asset's interface, e.g. 'ERC20' - options: { - address: string // The hexadecimal Starknet address of the token contract - symbol?: string // A ticker symbol or shorthand, up to 5 alphanumerical characters - decimals?: number // The number of asset decimals - image?: string // A string url of the token logo - name?: string // The name of the token - not in spec - } -} - -/** - * EIP-3085: - * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3085.md - */ -export interface AddStarknetChainParameters { - id: string - chainId: string // A 0x-prefixed hexadecimal string - chainName: string - rpcUrls?: string[] - blockExplorerUrls?: string[] - - nativeCurrency?: { - address: string // Not part of the standard, but required by Starknet as it can work with any ERC20 token as the fee token - name: string - symbol: string // 2-6 characters long - decimals: number - } // Currently ignored. - iconUrls?: string[] // Currently ignored. -} - -export interface SwitchStarknetChainParameters { - chainId: string // A 0x-prefixed hexadecimal string -} - -// see https://community.starknet.io/t/snip-deployment-interface-between-dapps-and-wallets/101923 -export interface GetDeploymentDataResult { - address: FELT // the expected address, used to double-check the returned data - class_hash: FELT // The class hash of the contract to deploy - salt: FELT // The salt used for the computation of the account address - calldata: FELT[] // An array of felts - sigdata?: FELT[] // An optional array of felts to be added in the signature - version: 0 | 1 // Cairo version (an integer) -} - -export type RpcMessage = - | { - type: "wallet_getPermissions" - result: Permission[] - } - | { - type: "wallet_requestAccounts" - params?: RequestAccountsParameters - result: string[] - } - | { - type: "wallet_watchAsset" - params: WatchAssetParameters - result: boolean - } - | { - type: "wallet_addStarknetChain" - params: AddStarknetChainParameters - result: boolean - } - | { - type: "wallet_switchStarknetChain" - params: SwitchStarknetChainParameters - result: boolean - } - | { - type: "wallet_requestChainId" - result: StarknetChainId // returns the chain ID of the current network - } - | { - type: "wallet_deploymentData" - result: GetDeploymentDataResult - } - | { - type: "starknet_addInvokeTransaction" - params: AddInvokeTransactionParameters - result: AddInvokeTransactionResult - } - | { - type: "starknet_addDeclareTransaction" - params: AddDeclareTransactionParameters - result: AddDeclareTransactionResult - } - | { - type: "starknet_addDeployAccountTransaction" - params: AddDeployAccountTransactionParameters - result: AddDeployAccountTransactionResult - } - | { - type: "starknet_signTypedData" - params: TypedData - result: string[] - } - | { - type: "starknet_supportedSpecs" - result: string[] // supported starknet specs' tags (see https://github.com/starkware-libs/starknet-specs) - } - +// Implement the StarknetWindowObject interface with the improved request method export interface StarknetWindowObject { id: string name: string version: string icon: string | { dark: string; light: string } - request: ( - call: Omit, - ) => Promise - on: ( - event: E["type"], - handleEvent: E["handler"], - ) => void - off: ( - event: E["type"], - handleEvent: E["handler"], - ) => void + request: RequestFn + on: WalletEventListener + off: WalletEventListener } declare global { diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 6533ce0..f1b7a8e 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -1,6 +1,7 @@ -import { Permission, type StarknetWindowObject } from "./StarknetWindowObject" +import { type StarknetWindowObject } from "./StarknetWindowObject" import discovery, { type WalletProvider } from "./discovery" import { LocalStorageWrapper } from "./localStorageStore" +import { Permission } from "./rpcMessage" import type { GetStarknetOptions, GetStarknetResult } from "./types" import { pipe } from "./utils" import { filterBy, filterByAuthorized } from "./wallet/filter" @@ -8,8 +9,9 @@ import { isWalletObj } from "./wallet/isWalletObject" import { scanObjectForWallets } from "./wallet/scan" import { sortBy } from "./wallet/sort" +export type { StarknetWindowObject } from "./StarknetWindowObject" + export type { - AccountChangeEventHandler, AddDeclareTransactionParameters, AddDeclareTransactionResult, AddDeployAccountTransactionParameters, @@ -17,19 +19,26 @@ export type { AddInvokeTransactionParameters, AddInvokeTransactionResult, AddStarknetChainParameters, - NetworkChangeEventHandler, RequestAccountsParameters, - RpcMessage, StarknetChainId, - StarknetWindowObject, SwitchStarknetChainParameters, + GetDeploymentDataResult, + WatchAssetParameters, TypedData, + RequestFn, + RpcMessage, + IsParamsOptional, + RpcTypeToMessageMap, +} from "./rpcMessage" + +export type { WalletEvents, - WatchAssetParameters, - GetDeploymentDataResult, -} from "./StarknetWindowObject" + AccountChangeEventHandler, + NetworkChangeEventHandler, + WalletEventHandlers, +} from "./walletEvents" -export { Permission } from "./StarknetWindowObject" +export { Permission } from "./rpcMessage" export type { DisconnectOptions, @@ -104,13 +113,15 @@ export function getStarknet( enable: async (wallet, options) => { await wallet.request({ type: "wallet_requestAccounts", - params: options, + params: { + silentMode: options?.silentMode, + }, }) // check for permissions - const permissions = (await wallet.request({ + const permissions = await wallet.request({ type: "wallet_getPermissions", - })) as Permission[] + }) if (!permissions?.includes(Permission.Accounts)) { throw new Error("Failed to connect to wallet") } diff --git a/packages/core/src/rpcMessage.ts b/packages/core/src/rpcMessage.ts new file mode 100644 index 0000000..045d5f2 --- /dev/null +++ b/packages/core/src/rpcMessage.ts @@ -0,0 +1,325 @@ +export enum StarknetChainId { + SN_MAIN = "0x534e5f4d41494e", + SN_GOERLI = "0x534e5f474f45524c49", +} + +export enum Permission { + Accounts = "accounts", +} + +type FELT = string + +type Call = { + contract_address: FELT + entrypoint: string + calldata?: FELT[] +} + +type SIERRA_ENTRY_POINT = { + selector: FELT + function_idx: number +} + +type StarknetMerkleType = { + name: string + type: "merkletree" + contains: string +} + +/** + * A single type, as part of a struct. The `type` field can be any of the EIP-712 supported types. + * + * Note that the `uint` and `int` aliases like in Solidity, and fixed point numbers are not supported by the EIP-712 + * standard. + */ +type StarknetType = + | { + name: string + type: string + } + | StarknetMerkleType + +/** + * The EIP712 domain struct. Any of these fields are optional, but it must contain at least one field. + */ +interface StarknetDomain extends Record { + name?: string + version?: string + chainId?: string | number +} + +/** + * The complete typed data, with all the structs, domain data, primary type of the message, and the message itself. + */ +export interface TypedData { + types: Record + primaryType: string + domain: StarknetDomain + message: Record +} + +/** + * INVOKE_TXN_V1 + * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + */ +export interface AddInvokeTransactionParameters { + /** + * Calls to invoke by the account + */ + calls: Call[] +} +export interface AddInvokeTransactionResult { + /** + * The hash of the invoke transaction + */ + transaction_hash: FELT +} + +/** + * BROADCASTED_DECLARE_TXN_V2 + * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + */ +export interface AddDeclareTransactionParameters { + /** + * The hash of the Cairo assembly resulting from the Sierra compilation + */ + compiled_class_hash: FELT + contract_class: { + /** + * The list of Sierra instructions of which the program consists + */ + sierra_program: FELT[] + /** + * The version of the contract class object. Currently, the Starknet OS supports version 0.1.0 + */ + contract_class_version: string + /** + * Entry points by type + */ + entry_points_by_type: { + CONSTRUCTOR: SIERRA_ENTRY_POINT[] + EXTERNAL: SIERRA_ENTRY_POINT[] + L1_HANDLER: SIERRA_ENTRY_POINT[] + } + /** + * The class ABI, as supplied by the user declaring the class + */ + abi?: string + } +} +export interface AddDeclareTransactionResult { + /** + * The hash of the declare transaction + */ + transaction_hash: FELT + /** + * The hash of the declared class + */ + class_hash: FELT +} + +/** + * DEPLOY_ACCOUNT_TXN_V1 + * @see https://github.com/starkware-libs/starknet-specs/blob/master/api/starknet_api_openrpc.json + */ +export interface AddDeployAccountTransactionParameters { + /** + * The salt for the address of the deployed contract + */ + contract_address_salt: FELT + /** + * The parameters passed to the constructor + */ + constructor_calldata: FELT[] + /** + * The hash of the deployed contract's class + */ + class_hash: FELT +} +export interface AddDeployAccountTransactionResult { + /** + * The hash of the deploy transaction + */ + transaction_hash: FELT + /** + * The address of the new contract + */ + contract_address: FELT +} + +/** + * EIP-1102: + * @see https://eips.ethereum.org/EIPS/eip-1102 + */ +export interface RequestAccountsParameters { + /** + * If true, the wallet will not show the wallet-unlock UI in case of a locked wallet, + * nor the dApp-approve UI in case of a non-allowed dApp. + */ + silentMode?: boolean +} + +/** + * EIP-747: + * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-747.md + */ +export interface WatchAssetParameters { + type: "ERC20" // The asset's interface, e.g. 'ERC20' + options: { + address: string // The hexadecimal Starknet address of the token contract + symbol?: string // A ticker symbol or shorthand, up to 5 alphanumerical characters + decimals?: number // The number of asset decimals + image?: string // A string url of the token logo + name?: string // The name of the token - not in spec + } +} + +/** + * EIP-3085: + * @see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3085.md + */ +export interface AddStarknetChainParameters { + id: string + chainId: string // A 0x-prefixed hexadecimal string + chainName: string + rpcUrls?: string[] + blockExplorerUrls?: string[] + + nativeCurrency?: { + address: string // Not part of the standard, but required by Starknet as it can work with any ERC20 token as the fee token + name: string + symbol: string // 2-6 characters long + decimals: number + } // Currently ignored. + iconUrls?: string[] // Currently ignored. +} + +export interface SwitchStarknetChainParameters { + chainId: string // A 0x-prefixed hexadecimal string +} + +// see https://community.starknet.io/t/snip-deployment-interface-between-dapps-and-wallets/101923 +export interface GetDeploymentDataResult { + address: FELT // the expected address, used to double-check the returned data + class_hash: FELT // The class hash of the contract to deploy + salt: FELT // The salt used for the computation of the account address + calldata: FELT[] // An array of felts + sigdata?: FELT[] // An optional array of felts to be added in the signature + version: 0 | 1 // Cairo version (an integer) +} + +/** + * Maps each RPC message type to its corresponding parameters and result type. + */ +export interface RpcTypeToMessageMap { + /** + * Get permissions from the wallet. + * @returns An array of permissions. + */ + wallet_getPermissions: { params?: never; result: Permission[] } + + /** + * Request accounts from the wallet. + * @param params Optional parameters for requesting accounts. + * @returns An array of account addresses as strings. + */ + wallet_requestAccounts: { + params?: RequestAccountsParameters + result: string[] + } + + /** + * Watch an asset in the wallet. + * @param params The parameters required to watch an asset. + * @returns A boolean indicating if the operation was successful. + */ + wallet_watchAsset: { params: WatchAssetParameters; result: boolean } + + /** + * Add a new Starknet chain to the wallet. + * @param params The parameters required to add a new chain. + * @returns A boolean indicating if the operation was successful. + */ + wallet_addStarknetChain: { + params: AddStarknetChainParameters + result: boolean + } + + /** + * Switch the current Starknet chain in the wallet. + * @param params The parameters required to switch chains. + * @returns A boolean indicating if the operation was successful. + */ + wallet_switchStarknetChain: { + params: SwitchStarknetChainParameters + result: boolean + } + + /** + * Request the current chain ID from the wallet. + * @returns The current Starknet chain ID. + */ + wallet_requestChainId: { params?: never; result: StarknetChainId } + + /** + * Get deployment data for a contract. + * @returns The deployment data result. + */ + wallet_deploymentData: { params?: never; result: GetDeploymentDataResult } + + /** + * Add an invoke transaction to the wallet. + * @param params The parameters required for the invoke transaction. + * @returns The result of adding the invoke transaction. + */ + starknet_addInvokeTransaction: { + params: AddInvokeTransactionParameters + result: AddInvokeTransactionResult + } + + /** + * Add a declare transaction to the wallet. + * @param params The parameters required for the declare transaction. + * @returns The result of adding the declare transaction. + */ + starknet_addDeclareTransaction: { + params: AddDeclareTransactionParameters + result: AddDeclareTransactionResult + } + + /** + * Add a deploy account transaction to the wallet. + * @param params The parameters required for the deploy account transaction. + * @returns The result of adding the deploy account transaction. + */ + starknet_addDeployAccountTransaction: { + params: AddDeployAccountTransactionParameters + result: AddDeployAccountTransactionResult + } + + /** + * Sign typed data using the wallet. + * @param params The typed data to sign. + * @returns An array of signatures as strings. + */ + starknet_signTypedData: { params: TypedData; result: string[] } + + /** + * Get the list of supported specifications. + * @returns An array of supported specification strings. + */ + starknet_supportedSpecs: { params?: never; result: string[] } +} + +export type RpcMessage = { + [K in keyof RpcTypeToMessageMap]: { type: K } & RpcTypeToMessageMap[K] +}[keyof RpcTypeToMessageMap] + +export type IsParamsOptional = + undefined extends RpcTypeToMessageMap[T]["params"] ? true : false + +export type RequestFn = ( + call: { type: T } & (IsParamsOptional extends true + ? { params?: RpcTypeToMessageMap[T]["params"] } + : { params: RpcTypeToMessageMap[T]["params"] }), +) => Promise diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 7c4f935..775775e 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -1,11 +1,9 @@ +import { StarknetWindowObject } from "./StarknetWindowObject" +import { WalletProvider } from "./discovery" import { IStorageWrapper } from "./localStorageStore" -import { Sort } from "./wallet/sort" +import { RequestAccountsParameters } from "./rpcMessage" import { FilterList } from "./wallet/filter" -import { - RequestAccountsParameters, - StarknetWindowObject, -} from "./StarknetWindowObject" -import { WalletProvider } from "./discovery" +import { Sort } from "./wallet/sort" export type { WalletProvider } from "./discovery" diff --git a/packages/core/src/wallet/filter.ts b/packages/core/src/wallet/filter.ts index d4460d4..c504827 100644 --- a/packages/core/src/wallet/filter.ts +++ b/packages/core/src/wallet/filter.ts @@ -1,5 +1,6 @@ -import { Permission, type StarknetWindowObject } from "../StarknetWindowObject" +import { type StarknetWindowObject } from "../StarknetWindowObject" import type { WalletProvider } from "../discovery" +import { Permission } from "../rpcMessage" export type FilterList = string[] interface FilterByOptions { @@ -35,9 +36,7 @@ export const filterByAuthorized = async ( wallets.map((w) => w .request({ type: "wallet_getPermissions" }) - .then((result) => - (result as Permission[])?.includes(Permission.Accounts), - ) + .then((result) => result.includes(Permission.Accounts)) .catch(() => false), ), ) diff --git a/packages/core/src/walletEvents.ts b/packages/core/src/walletEvents.ts new file mode 100644 index 0000000..4933fda --- /dev/null +++ b/packages/core/src/walletEvents.ts @@ -0,0 +1,17 @@ +import { StarknetChainId } from "./rpcMessage" + +export type AccountChangeEventHandler = (accounts?: string[]) => void + +export type NetworkChangeEventHandler = ( + chainId?: StarknetChainId, + accounts?: string[], +) => void + +export interface WalletEventHandlers { + accountsChanged: AccountChangeEventHandler + networkChanged: NetworkChangeEventHandler +} + +export type WalletEvents = { + [E in keyof WalletEventHandlers]: { type: E; handler: WalletEventHandlers[E] } +}[keyof WalletEventHandlers] From 694a3116f41d19ec93112b7ab03f1d351e0ada40 Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Wed, 14 Feb 2024 14:35:28 +0000 Subject: [PATCH 15/16] chore: export more types --- packages/core/src/main.ts | 1 + packages/core/src/rpcMessage.ts | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index f1b7a8e..1deeaff 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -29,6 +29,7 @@ export type { RpcMessage, IsParamsOptional, RpcTypeToMessageMap, + RequestFnCall, } from "./rpcMessage" export type { diff --git a/packages/core/src/rpcMessage.ts b/packages/core/src/rpcMessage.ts index 045d5f2..5792d5f 100644 --- a/packages/core/src/rpcMessage.ts +++ b/packages/core/src/rpcMessage.ts @@ -1,6 +1,7 @@ export enum StarknetChainId { SN_MAIN = "0x534e5f4d41494e", SN_GOERLI = "0x534e5f474f45524c49", + SN_SEPOLIA = "0x534e5f5345504f4c4941", } export enum Permission { @@ -318,8 +319,12 @@ export type RpcMessage = { export type IsParamsOptional = undefined extends RpcTypeToMessageMap[T]["params"] ? true : false +export type RequestFnCall = { + type: T +} & (IsParamsOptional extends true + ? { params?: RpcTypeToMessageMap[T]["params"] } + : { params: RpcTypeToMessageMap[T]["params"] }) + export type RequestFn = ( - call: { type: T } & (IsParamsOptional extends true - ? { params?: RpcTypeToMessageMap[T]["params"] } - : { params: RpcTypeToMessageMap[T]["params"] }), + call: RequestFnCall, ) => Promise From 4a477fd71a2cd1ce5b150b5f9fd465287fae2991 Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Thu, 15 Feb 2024 13:21:10 +0000 Subject: [PATCH 16/16] chore: add changeset --- .changeset/famous-cougars-bathe.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/famous-cougars-bathe.md diff --git a/.changeset/famous-cougars-bathe.md b/.changeset/famous-cougars-bathe.md new file mode 100644 index 0000000..53d2a40 --- /dev/null +++ b/.changeset/famous-cougars-bathe.md @@ -0,0 +1,6 @@ +--- +"get-starknet-core": major +"get-starknet": major +--- + +new wallet snip