πIntroduction
Architecture
The module operates as an IBC middleware hook that:
Intercepts incoming IBC transfer packets
Parses hook data from the transfer memo
Executes the IBC transfer first (to receive the tokens)
Executes the custom hook actions (swap, transfer, etc.)
Returns an error acknowledgement if the hook fails, rolling back the entire transaction
Warning: Native x/badges assets cannot be IBC transferred. Only x/bank assets can be.Key Concepts
Hook Data Format
Hook data is specified in the IBC transfer memo using JSON format. The module supports the swap_and_action format, similar to Skip Protocol's implementation with a couple minor differences (no affiliates and some other features may nto be supproted).
Swap and Action
The primary hook type is swap_and_action, which:
Executes a swap operation using the received tokens
Performs a post-swap action (local transfer or IBC transfer)
Intermediate Sender Address
The module derives an intermediate sender address from the IBC channel and original sender. This address is used to:
Receive the IBC transfer tokens
Execute the swap operation
Send tokens to the final destination
Use here for generation if needed
import { deriveIntermediateSender } from 'bitbadgesjs-sdk';
// deriveIntermediateSender('channel-0', 'osmo1...', 'bb');
export function deriveIntermediateSender(channel: string, originalSender: string, bech32Prefix: string)Atomic Execution
All operations are executed atomically:
If the IBC transfer succeeds but the hook fails, the entire transaction is rolled back
If the hook fails, an error acknowledgement is returned, preventing the IBC transfer from completing
State changes are only committed if all operations succeed
Hook Data Structure
HookData
type HookData struct {
SwapAndAction *SwapAndAction `json:"swap_and_action,omitempty"`
}SwapAndAction
type SwapAndAction struct {
UserSwap *UserSwap `json:"user_swap,omitempty"`
MinAsset *MinAsset `json:"min_asset,omitempty"`
TimeoutTimestamp *uint64 `json:"timeout_timestamp,omitempty"`
PostSwapAction *PostSwapAction `json:"post_swap_action,omitempty"`
}UserSwap
type UserSwap struct {
SwapExactAssetIn *SwapExactAssetIn `json:"swap_exact_asset_in,omitempty"`
}SwapExactAssetIn
type SwapExactAssetIn struct {
SwapVenueName string `json:"swap_venue_name,omitempty"`
Operations []Operation `json:"operations"`
}Operation
type Operation struct {
Pool string `json:"pool"` // Pool ID as string
DenomIn string `json:"denom_in"`
DenomOut string `json:"denom_out"`
}PostSwapAction
type PostSwapAction struct {
IBCTransfer *IBCTransferInfo `json:"ibc_transfer,omitempty"`
Transfer *TransferInfo `json:"transfer,omitempty"`
}Note: Exactly one of IBCTransfer or Transfer must be specified.
Validation Rules
Post-swap action is required: The
post_swap_actionfield must be presentExactly one action: Either
ibc_transferortransfermust be specified, but not bothSwap required: If
post_swap_actionis defined, a swap must also be definedSingle-hop swaps: Only single-operation swaps are currently supported
Denom matching: The swap's
denom_inmust match the received token denomination and the amount will automatically be the received amountChannel validation: For IBC transfers, the source channel must exist
Address validation: All addresses must be valid Bech32 addresses
Capability validation: Channel capabilities must exist for IBC transfers
Post-Swap Actions
Local Transfer
Transfers the swapped tokens to a local address:
{
"transfer": {
"to_address": "bb1..."
}
}IBC Transfer
Sends the swapped tokens to another chain via IBC:
{
"ibc_transfer": {
"ibc_info": {
"source_channel": "channel-0",
"receiver": "bb1...",
"memo": "...",
"recover_address": "bb1..."
}
}
}Limitations
Single-hop swaps only: Multi-hop swaps are not supported
GAMM pools only: Only GAMM pool swaps are supported
No BitBadges IBC transfers: BitBadges denominations cannot be IBC transferred
Required swap: A swap is required if using post-swap actions (use packet-forward-middleware for transfers without swaps)
Usage Example
Swap and Local Transfer
{
"swap_and_action": {
"user_swap": {
"swap_exact_asset_in": {
"swap_venue_name": "bitbadges-poolmanager",
"operations": [
{
"pool": "1",
"denom_in": "ubadge",
"denom_out": "ibc/ABC..."
}
]
}
},
"min_asset": {
"native": {
"denom": "ibc/ABC...",
"amount": "1000000"
}
},
"post_swap_action": {
"transfer": {
"to_address": "bb1..."
}
}
}
}Swap and IBC Transfer
{
"swap_and_action": {
"user_swap": {
"swap_exact_asset_in": {
"swap_venue_name": "bitbadges-poolmanager",
"operations": [
{
"pool": "1",
"denom_in": "ubadge",
"denom_out": "ibc/ABC..."
}
]
}
},
"min_asset": {
"native": {
"denom": "ibc/ABC...",
"amount": "1000000"
}
},
"timeout_timestamp": 1234567890000000000,
"post_swap_action": {
"ibc_transfer": {
"ibc_info": {
"source_channel": "channel-0",
"receiver": "cosmos1xyz789...",
"recover_address": "cosmos1intermediate..."
}
}
}
}
}Last updated