Rerouted (renamed, verified). The GitHub user or repository was renamed. The tag is still there, at the new name. The Lamdera package server serves a copy recovered from https://github.com/IntrepidShape/elm-web3.
What we checked: The repo moved to github.com/IntrepidShape/elm-web3 and tag 1.0.0 is there; its commit 9d919244f65e is from 2026-05-09 11:48 UTC, before the version was published (2026-05-09 11:58 UTC); elm.json is byte-identical to package.elm-lang.org's; the exposed modules match docs.json; the zip's SHA-1 is not the published one (GitHub's zip no longer comes out byte for byte the same), so the contents were checked instead.
The Lamdera compiler uses this copy and prints a one-line notice saying so. elm itself fails to download this version.
Details · package.elm-lang.org's zip: https://github.com/intrepidshape/elm-web3/zipball/1.0.0/
EIP-712 typed data signing and EIP-191 personal signing.
Build a typed data request, encode it for the JS port, decode the signature response.
Use the SignState machine to track the lifecycle of a single sign request.
import Dict
import Json.Encode as E
import Web3.Sign as Sign
permitRequest : T.Address -> T.Address -> BigInt -> Int -> Sign.TypedData
permitRequest owner spender value nonce =
Sign.typedData
{ domain =
{ name = Just "MyToken", version = Just "1"
, chainId = Just 369, verifyingContract = Just tokenAddress
, salt = Nothing
}
, types =
Dict.fromList
[ ( "Permit"
, [ { name = "owner", typeName = "address" }
, { name = "spender", typeName = "address" }
, { name = "value", typeName = "uint256" }
, { name = "nonce", typeName = "uint256" }
, { name = "deadline", typeName = "uint256" }
]
)
]
, primaryType = "Permit"
, message = E.object [ ... ]
}
-- Send via port:
web3Cmd (Sign.encode "permit-1" signerAddress (permitRequest owner spender value nonce))
-- Receive via port (use signatureDecoder for the raw sig string):
case D.decodeValue Sign.signatureDecoder incoming of
Ok sig -> -- sig is the 0x-prefixed signature
Err _ -> -- not a sign responseSign state machine — tracks one in-flight request:
type SignState
= SignIdle
| SignPending String -- id
| Signed String String -- id, signature
| SignFailed String String -- id, error
| SignRejected String -- id
-- Usage:
( { model | signState = Sign.startSign "permit-1" model.signState }
, web3Cmd (Sign.encode "permit-1" addr request)
)
-- On port response:
newSignState = Sign.signUpdate signMsg model.signStateEIP-712 domain separator parameters. All fields are optional; include only those your contract's domain hash covers.
A single field in a struct type definition.
Construct a TypedData value.
Encode a TypedData request as a port command.
web3Cmd (Sign.encode "my-id" signerAddress request)The id is echoed back in the signed response so you can match
responses to requests when multiple signing requests are in flight.
Sign an arbitrary message with personal_sign (EIP-191).
Used for login flows and simple off-chain authentication. The wallet will display the raw message to the user before signing.
web3Cmd (Sign.personalSign "login-1" signerAddress "Sign in to MyDapp")Responses arrive on the same signed tag as EIP-712 — use signatureDecoder.
Decode the signed response from the JS port.
case D.decodeValue Sign.signatureDecoder incoming of
Ok sig ->
-- sig : String — the 0x-prefixed signature
Err _ ->
-- handle decode errorSigning state machine. Tracks the lifecycle of a single sign request.
SignIdle — no sign request in progressSignPending id — awaiting user approval for request idSigned id sig — user approved; sig is the 0x-prefixed signatureSignFailed id err — signing failed (wallet error, network error)SignRejected id — user explicitly cancelled in wallet UIMessages from the JS sign port.
Transition from SignIdle to SignPending for the given correlation id.
All other states are unchanged (a sign already in flight is not replaced).
Update sign state from a port message. Terminal states never transition out.
True if the sign state is terminal (no more updates expected).
An EIP-712 typed data signing request.