intrepidshape/elm-web3/1.2.3

NOTE: the latest version is 3.0.0

Web3.Wallet

Wallet connection state machine.

The wallet is modeled as an explicit state — you can't accidentally call a contract without a connected wallet because the compiler won't give you an Address from a Disconnected state.

case model.wallet of
    Connected info ->
        -- info.address : T.Address — only available here
        buy info.address amount


    WrongChain _ _ ->
        -- wallet is connected but on the wrong chain
        button [ onClick SwitchChain ] [ text "Switch chain" ]


    ReadOnly ->
        -- rpcUrl configured but no wallet; reads work, writes will fail
        viewReadOnlyBanner


    _ ->
        showConnectButton

EIP-6963 multi-wallet discovery — listen for WalletsDiscovered on the port and present the list to the user; call selectWallet rdns when they pick.

Typical connection flow:

  1. User clicks "Connect" → call startConnect on state, send connect via port.
  2. WalletsDiscovered providers arrives → show picker if providers is non-empty.
  3. User picks a wallet → send selectWallet rdns via port.
  4. WalletConnected addr chainId arrives → update transitions to Connected or WrongChain.
  5. If WrongChain → send switchChain expectedChain via port.

For native balance queries, use Web3.Balance. For adding chains, use addChain with a ChainConfig record and follow up with switchChain.

type State
= Disconnected
| ReadOnly
| Connecting
| Connected ConnectedInfo
| WrongChain ConnectedInfo ChainId
| Error String

Wallet connection state. Every possible state is explicit.

  • Disconnected — no wallet detected, no rpcUrl configured
  • ReadOnly — rpcUrl is present but no wallet; reads work, writes will fail
  • Connecting — wallet connection in progress
  • Connected — wallet connected on the expected chain
  • WrongChain — wallet connected but on the wrong chain
  • Error — unrecoverable error
type Msg
= WalletConnected String Int
| WalletDisconnected
| ChainChanged Int
| AccountChanged String
| WalletError String
| WalletsDiscovered (List WalletProvider)
| ReadOnlyMode
| ChainAdded
| SwitchChainOk Int
| AssetWatched
| GotPermissions (List String)

Messages from the JS wallet port.

= RequestConnect
| RequestDisconnect
| RequestSwitchChain Int
| RequestSelectWallet String
| RequestAddChain ChainConfig
| RequestWatchAsset
{ address : Address
, symbol : String
, decimals : Int
, image : String
}
| RequestPermissions
| GetPermissions

Commands to send to JS via port.

type alias WalletProvider =
{ name : String
, icon : String
, rdns : String
}

A wallet provider discovered via EIP-6963.

type alias ChainConfig =
{ chainId : Int
, chainName : String
, rpcUrls : List String
, nativeCurrency :
{ name : String
, symbol : String
, decimals : Int
}
, blockExplorerUrls : List String
}

Configuration for adding a new chain to the wallet (EIP-3085).

Update wallet state from a port message.

Transition to Connecting state before sending the connect port command.

Call this when the user clicks the connect button, then send connect via the port:

( { model | wallet = Wallet.startConnect model.wallet }
, web3Cmd (Wallet.encode Wallet.connect)
)

Valid transitions: Disconnected → Connecting, Error _ → Connecting. All other states are unchanged (connecting while already connected is a no-op).

Command to request wallet connection.

Command to request wallet disconnection.

Command to switch chain.

Command to select a specific wallet by its RDNS identifier (EIP-6963).

selectWallet "io.metamask"
addChain : ChainConfig -> WalletCmd

Request wallet_addEthereumChain (EIP-3085) to add a new network.

addChain
    { chainId = 369
    , chainName = "PulseChain"
    , rpcUrls = [ "https://rpc.pulsechain.com" ]
    , nativeCurrency = { name = "Pulse", symbol = "PLS", decimals = 18 }
    , blockExplorerUrls = [ "https://scan.pulsechain.com" ]
    }
{ address : Address
, symbol : String
, decimals : Int
, image : String
}

Command to add a token to the wallet UI (EIP-747).

Command to request wallet permissions (EIP-2255).

Command to get current wallet permissions (EIP-2255).

isConnected : State -> Bool

True if the wallet is in the Connected state.

isReadOnly : State -> Bool

True if in ReadOnly mode (rpcUrl present, no wallet). Reads work; writes will fail.

Extract the connected address, if any.

Extract the connected chain ID, if any.

encode : WalletCmd -> Value

Encode a WalletCmd for the JS port.

decoder : Decoder Msg

Decode a Msg from the JS wallet port.