- The player gets an embedded, self-custodial WDK wallet with no seed phrase to manage.
- The yield agent is an autonomous WDK agent wallet that signs its own on-chain moves.
The player wallet is created with
@tetherto/wdk-wallet-evm in the dApp; the agent wallet uses the
same WDK primitives on the server through Goaly’s thin @goaly/plugin-wdk wrapper. Same kit, both
sides.The player’s embedded wallet
Every player gets a self-custodial wallet whose keys live on their device — created and signed with WDK. There is no seed phrase to write down, screenshot, or lose. The trick: instead of generating a random seed, Goaly derives the wallet deterministically from a sign-in signature, so it always restores from the wallet the user already has.Sign in
The user connects an external wallet and signs a fixed EIP-712 “sign in” message (no nonce,
no timestamp). Because the payload never changes, the same wallet always produces the same
signature.
Derive a seed
Goaly hashes that signature (
keccak256) into 32 bytes of entropy and expands it into a 24-word
BIP-39 mnemonic. This never leaves the browser and is never shown to the user.Create the WDK account
WDK’s
WalletManagerEvm turns the mnemonic into an EVM account on the standard BIP-44 path
m/44'/60'/0'/0/0 — the player’s embedded Goaly account.Because the account is derived from a deterministic signature, it is fully recoverable: if a
device is wiped, the user reconnects the same external wallet, re-signs, and WDK re-derives the
exact same address. Nothing to back up, nothing to leak.
The autonomous yield agent wallet
To make prizes as big as possible, Goaly runs an autonomous yield agent — and it runs on its own WDK wallet (WdkWallet / KeyWallet, both implementing the same WalletProvider interface from
@goaly/plugin-wdk). This is “agent wallet meets autonomous finance,” built on WDK primitives:
- Reads the market — it polls the live APY of each Morpho USD₮0/USDC vault and where the pooled principal currently sits.
- Decides — it computes the best risk-adjusted allocation across the vault’s whitelisted strategies.
- Signs for itself — using its WDK wallet, it can propose and sign its own
rebalance()call and settle it on-chain in USD₮0. No human has to co-sign each move.
The agent is currently advisory: it surfaces and signs a recommended allocation, but actually
moving funds stays governance-gated for launch. You can watch it decide live at
api.goaly.fun/agent.
Safety: separation, roles, and recovery
WDK gives Goaly clean self-custody; the protocol’s design keeps that power tightly boxed. Clean separation. App and agent logic is fully separate from wallet execution. Both wallets implement one smallWalletProvider interface (createWallet / signMessage / send /
sendTransaction), so signing is the only thing the wallet ever does — the business logic never
touches keys.
Least-privilege on-chain roles. Even a fully autonomous agent can’t run off with the money,
because the on-chain roles are minimal:
| Role | May do | May not do |
|---|---|---|
| AGENT (yield wallet) | rebalance between the buffer and whitelisted strategies | Touch user principal, or move funds to an EOA / cross-chain |
| ORACLE / PROPOSER | Open and settle markets | Move funds |
| GUARDIAN | Pause the protocol | Move funds |
| GOVERNANCE (admin) | Upgrade / configure — a Timelock + Safe | — |
Roadmap: WDK’s account-abstraction support opens the door to gasless / sponsored
predictions and claims, so a player never needs to hold ETH for gas. Planned, not yet shipped.
WDK primitives used
Wallet creation
Deriving each account from a seed.
Accounts
BIP-44 accounts + addresses.
Signing
Signing messages and transactions.
| WDK primitive | What it does | Where Goaly uses it |
|---|---|---|
| Wallet creation | new WalletManagerEvm(seed) from a BIP-39 seed | Player wallet in apps/app (seed from the sign-in signature); agent wallet on the server |
| Accounts | getAccount(index) → getAddress() on BIP-44 m/44'/60'/0'/0/0 | The player’s embedded Goaly address; the agent’s own address |
| Signing | account.sign(...) / transfer / sendTransaction | Player: stake, claim, send/tip USDT. Agent: sign & settle rebalance() on-chain |
See the wallet wrapper
packages/plugin-wdk — WdkWallet (Tether WDK, on-device seed), KeyWallet (server signer), and
MockWallet (deterministic dev stand-in), all behind one WalletProvider interface.