Smart wallets
If you just need to interact with smart contracts, then the easiest thing to do is just build one of our smart wallets. You’ll be able to see all of your wallets in the dashboard athttps://app.goldsky.com/{projectId}/dashboard/compose/{appName}.
Create a smart wallet
Using wallets
Once you have a wallet created you can use it to write to smart contracts, see the full smart contract docs for more detailssendTransaction
For lower-level control, usesendTransaction to send a transaction with pre-encoded calldata. This is useful when you need to encode the transaction data yourself, pass specific gas parameters, or interact with contracts in ways that writeContract doesn’t cover.
The
nonce parameter is only supported with EOA (private key) wallets. Smart wallets manage nonces internally.getBalance
Check the native token balance of any wallet:Wallet properties
Every wallet exposesname and address as read-only properties:
EOA wallets
You can also use EOAs that you already own, this allows you to self-fund gas, send and receive tokens in your tasks, and interact with smart contracts in which an EOA you already own has privileges on particular contract methods. Currently we support storing your EOA private key in Compose’s secret management system, but in the future you’ll be able to use private keys that are secured within TEEs. EOA wallets never pass their private keys outside of the task process and they sign requests passed in unsigned from the host process. When tasks run in TEEs they’ll be able to use private keys very securely within the TEE, never exposing it to any part of the stack outside of the TEE. This will empower Compose to run the most security sensitive use cases. First, you’ll need to store the private key in Goldsky’s secret management system and reference it in your compose.yaml file. You can see details on how to do that in the Secrets docs. Once you have your private key secret stored, you can use it to create a wallet:Webhook wallets
evm.webhookWallet sends gas-sponsored transactions from an address you already hold. Compose never sees the private key. It builds the ERC-4337 UserOperation, including paymaster data, POSTs that payload to a signing URL you host, then submits the signed operation.
Create a webhook wallet
url must be http:// or https://. address must be a 20-byte hex address. headers are copied onto every POST. Store the URL, address, and any auth token as secrets.
Compose saves the address on the app, so the wallet shows up in the dashboard.
Webhook wallets implement the same IWallet as smart wallets and EOAs (writeContract, sendTransaction, readContract, simulate, getBalance). Writes are always gas-sponsored.
Cloud only
Webhook wallets run in deployed apps. Creating one in local dev throws:--fork-chains still POSTs to your webhook so you can test signing. Submit fails after that because there is no local bundler.
Request bodies
Compose POSTs JSON tourl with Content-Type: application/json plus any headers you set. The request times out after 120 seconds. Bigint fields in the body are sent as decimal strings.
If the wallet is not yet EIP-7702 delegated on the target chain, Compose asks the webhook to sign the authorization first:
r and s as 32-byte hex strings, and either yParity (0 or 1) or v (27, 28, 0, or 1). If you also return address, chainId, or nonce, they must match the request. contractAddress is the EIP-7702 implementation, not your wallet.
Every sponsored write then asks the webhook to sign the UserOperation’s EIP-712 typed data:
{ "signature": "0x..." }. A non-JSON body, a missing signature, or a non-2xx status fails the task. Do not broadcast from the webhook. Return the signature; Compose submits the sponsored UserOperation.
nonce on sendTransaction is ignored, as with other gas-sponsored wallets. A task retry prepares a new UserOperation, so Compose does not reuse a previous webhook signature.
Signing server
The other side ofwebhookWallet is one POST handler on a server you host. sign7702Authorization and signTypedData are whatever holds the key (Turnkey, Fireblocks, an HSM, a local key). Sign and return. Do not broadcast.
Impersonated wallets
When testing locally with--fork-chains, you may need to call contract methods that are restricted to a specific address — for example, an owner-only admin function or a method guarded by an access control list. Normally you’d need the private key for that address, but with the --impersonate flag you can act as any address on the local TEVM fork using only its public address.
This is useful when:
- You want to test privileged contract methods without giving your local environment access to the private key
- You need to debug interactions with a contract where only a specific address has permission to call certain methods
- You’re testing against a forked mainnet contract and want to simulate actions from an address you control on-chain but don’t want to expose the key locally
Usage
Pass--impersonate alongside --fork-chains when starting your app. The flag takes a comma-separated list of walletName=address mappings:
.address will resolve to the impersonated address, and all contract interactions (reads, writes, and simulations) will execute as that address on the local fork.
name that matches an entry in the impersonate map, the impersonated address takes precedence and the private key is effectively ignored on the fork:
--impersonate requires --fork-chains and only works in local development. All impersonated transactions execute on your local TEVM fork — nothing is sent to the actual chain. When you deploy to cloud, wallets resolve normally.Gas sponsoring
By default, smart wallets (wallets created without a private key) use gas sponsoring so you don’t have to think about managing gas funding. Smart wallets use EIP-7702 delegation for account abstraction, with gas costs handled through ERC-4337 UserOperations. Webhook wallets are always gas-sponsored. You pay the gas bill as part of your normal monthly Goldsky bill, avoiding the complex budgetary and tax issues of purchasing gas tokens. When you don’t use gas sponsoring, you’ll need to get your wallet address from the compose dashboard athttps://app.goldsky.com/{projectId}/dashboard/compose/{appName}
and then transfer gas tokens to that wallet through a wallet or an exchange.
Gas sponsoring with EOA (private key) wallets
You can also opt into gas sponsoring for EOA wallets by passingsponsorGas: true when creating the wallet. Compose delegates the EOA via EIP-7702 on first use and routes transactions through ERC-4337 UserOperations, just like smart wallets — you keep full control of the key and signing, but you don’t have to fund the wallet with native gas tokens.
Sponsored EOA transactions only run in deployed apps. Running with
sponsorGas: true locally will throw a clear error that tells you to either remove sponsorGas, fund the wallet manually, or re-run with --fork-chains to exercise the sponsored flow against a forked chain. In --fork-chains mode the transaction is executed against the local fork (where gas is free), and you’ll see a warning reminding you the sponsored flow only takes effect once deployed to cloud.Gas usage in the dashboard
Every sponsored or self-paid transaction emits a run event withevm.gas_used and evm.total_cost_wei attributes (both decimal strings in wei) so you can audit per-transaction gas spend from the Compose dashboard at https://app.goldsky.com/{projectId}/dashboard/compose/{appName}. On OP Stack L2s (Lisk, Base, Optimism, and friends) evm.total_cost_wei includes the L1 data fee, which typically dominates the total cost — reading gasUsed × effectiveGasPrice from the receipt alone will under-report by roughly two orders of magnitude.
Gas pricing
For non-sponsored transactions, Compose uses automatic gas estimation with sensible defaults. If you need precise control over gas parameters, usesendTransaction instead of writeContract and specify maxFeePerGas, maxPriorityFeePerGas, and gas explicitly.
writeContract automatically simulates the transaction before submitting it, catching revert errors early. sendTransaction does not simulate — it submits directly.