Configuration
Configuration options for @tetherto/wdk-wallet-solana-gasless.
Wallet Configuration
WalletManagerSolanaGasless accepts a seed phrase or seed bytes plus a Solana gasless wallet configuration:
import WalletManagerSolanaGasless from '@tetherto/wdk-wallet-solana-gasless'
const config = {
provider: 'https://api.devnet.solana.com',
commitment: 'confirmed',
paymasterUrl: 'https://your-kora-paymaster.example',
paymasterAddress: 'Paymaster111111111111111111111111111111111',
paymasterToken: {
address: 'TokenMint111111111111111111111111111111111'
},
transferMaxFee: 1000000n,
transactionMaxFee: 1000000n
}
const wallet = new WalletManagerSolanaGasless(seedPhrase, config)
const account = await wallet.getAccount(0)Account Configuration
You can also construct an owned or read-only account directly:
import {
WalletAccountReadOnlySolanaGasless,
WalletAccountSolanaGasless
} from '@tetherto/wdk-wallet-solana-gasless'
const account = new WalletAccountSolanaGasless(seedPhrase, "0'/0'", config)
const readOnlyAccount = new WalletAccountReadOnlySolanaGasless('SolanaAddress...', {
provider: 'https://api.devnet.solana.com',
commitment: 'confirmed',
paymasterUrl: 'https://your-kora-paymaster.example',
paymasterAddress: 'Paymaster111111111111111111111111111111111',
paymasterToken: {
address: 'TokenMint111111111111111111111111111111111'
}
})Read-only accounts do not accept transferMaxFee or transactionMaxFee in their public type because they cannot send transfers or sign transactions.
Configuration Options
provider
Solana RPC endpoint, or an ordered list of RPC endpoints for failover. This is required for balance reads, blockhash lookup, quotes, signing transactions, sending transactions, and transfers.
Type: string | string[]
Example:
const config = {
provider: [
'https://api.devnet.solana.com',
'https://backup-solana-rpc.example'
]
}rpcUrl
Deprecated alias for provider, inherited from the base Solana wallet module. New code should use provider.
Type: string | string[]
commitment
Solana commitment level used for RPC reads such as balances, blockhashes, and receipts.
Type: 'processed' | 'confirmed' | 'finalized'
paymasterUrl
Kora-compatible paymaster RPC endpoint, Kora client options object, or ordered failover list.
Type: string | KoraClientOptions | Array<string | KoraClientOptions>
Required: Yes
Example:
const config = {
paymasterUrl: [
'https://primary-paymaster.example',
{ rpcUrl: 'https://backup-paymaster.example' }
]
}An empty paymasterUrl array throws an error.
paymasterAddress
Solana address used as the transaction fee payer. For prebuilt TransactionMessage inputs, an explicit feePayer must be absent or equal to this address.
Type: string
Required: Yes
paymasterToken
Token used by the paymaster to quote and charge fees.
Type:
type PaymasterTokenConfig = {
address: string
}Required: Yes
The module passes paymasterToken.address to the paymaster as the fee token and returns fees in that token's base units. For an unsigned flow, it derives the paymaster's associated token account for this mint, requires the returned payment instruction to be an SPL Token Transfer or TransferChecked to that account, and reads the instruction's encoded u64 amount instead of trusting separate quote metadata.
Beta.4 converts that decoded unsigned-flow u64 through JavaScript Number before converting it back to bigint. Amounts above Number.MAX_SAFE_INTEGER can be rounded in quotes, cap comparisons, and returned fees. Constrain the trusted paymaster's fee policy to at most 9007199254740991 base units; using a bigint input alone does not remove this internal boundary.
retries
Additional retry attempts used by failover providers when provider or paymasterUrl is an ordered list.
Type: number
Default: 3
transferMaxFee
Maximum allowed paymaster fee for transfer() calls, in the configured paymaster token's base units. transfer() throws when the quoted fee is greater than this cap.
Type: number | bigint
Required: No
Example:
const result = await account.transfer({
token: 'TokenMint111111111111111111111111111111111',
recipient: 'Recipient1111111111111111111111111111111',
amount: 1000000n
}, {
transferMaxFee: 500000n
})transactionMaxFee
Maximum allowed paymaster fee for sendTransaction() and signTransaction() calls, in the configured paymaster token's base units. For unsigned inputs, the module obtains the payment instruction and checks this cap before either the account or paymaster signs, subject to the Number.MAX_SAFE_INTEGER conversion boundary above. For the exact FullySignedTransaction produced by signTransaction(), it decodes a matching embedded payment amount and checks this cap before broadcasting through Solana RPC. A fee equal to the cap is allowed; only a greater fee is rejected.
For arbitrary signed input, this is not a fail-closed validator: beta.4 returns 0n when no matching payment instruction is found and can then broadcast because the cap comparison passes. Independently validate untrusted signed payloads or reject them before this API.
Type: number | bigint
Required: No
Example:
const result = await account.sendTransaction({
to: 'Recipient1111111111111111111111111111111',
value: 1000000n
}, {
transactionMaxFee: 500000n
})Paymaster Overrides
Quote, send, sign, and transfer methods accept a second configuration object for per-call fee-token and fee-cap overrides:
const quote = await account.quoteTransfer({
token: 'TokenMint111111111111111111111111111111111',
recipient: 'Recipient1111111111111111111111111111111',
amount: 1000000n
}, {
paymasterToken: {
address: 'AlternateFeeMint11111111111111111111111111'
},
transferMaxFee: 500000n
})In 1.0.0-beta.4, overrides support paymasterToken, transferMaxFee, and transactionMaxFee. Use transferMaxFee for transfer() fee protection and transactionMaxFee for sendTransaction() or signTransaction() fee protection. quoteTransfer() and quoteSendTransaction() return estimates without enforcing either cap.
For an already signed transaction, its payment token and amount are fixed in the signed message. quoteSendTransaction(signedTransaction) searches for a matching embedded payment and does not use the per-call token override. On sendTransaction(signedTransaction, { transactionMaxFee }), only the fee cap is relevant before direct RPC broadcast; an override cannot replace the signed payment token. In beta.4, a missing match returns 0n instead of rejecting, so restrict this path to exact locally produced output or perform independent signed-message validation.
Security Considerations
- Use HTTPS Solana RPC and paymaster endpoints.
- Use RPC endpoints that serve the same Solana network when enabling failover.
- Keep paymaster tokens funded for the accounts that need sponsored transactions.
- Set
transferMaxFeefor token transfers andtransactionMaxFeefor send/sign flows when your application needs fee protection. - Keep every trusted paymaster payment at or below
Number.MAX_SAFE_INTEGERbase units because beta.4's unsigned path converts the decodedu64throughNumber. - Validate the paymaster address and paymaster token address before using them in production configuration.
- Treat
Invalid payment instruction from paymaster.as a failed safety check. Do not sign, send, or retry by accepting a different destination automatically; verify the paymaster and token configuration first. - Do not accept arbitrary
FullySignedTransactioninput as validated by the signed send path; a missing matching payment instruction produces0ninstead of an error in beta.4. - Call
dispose()on owned accounts and wallet managers when private keys are no longer needed.