Skip to main content
There are several types of wallets and wallet behaviors that compose supports.

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 at https://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 details
You can also make or simulate transactions with methods on the Wallet class:

sendTransaction

For lower-level control, use sendTransaction 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.
You can also pass explicit gas parameters for full control over fees and gas limits:
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 exposes name 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 to url 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:
Respond with 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:
Respond with { "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 of webhookWallet 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:
You can impersonate multiple wallets at once:
Your task code stays exactly the same — just reference the wallet by name as usual. The wallet’s .address will resolve to the impersonated address, and all contract interactions (reads, writes, and simulations) will execute as that address on the local fork.
Impersonation also works with private-key wallets. If a private-key wallet has a 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 at https://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 passing sponsorGas: 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 with evm.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, use sendTransaction 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.

Override default gas sponsoring behavior

Full wallet interface