UNPKG

opnet

Version:

The perfect library for building Bitcoin-based applications.

666 lines (531 loc) 17.7 kB
# MotoSwap ABIs This guide covers the MotoSwap DEX contract ABIs. ## Overview MotoSwap is a decentralized exchange on OPNet. It consists of factory, router, pool, and staking contracts. --- ## Available Contracts | Contract | Interface | ABI | |----------|-----------|-----| | Factory | `IMotoswapFactoryContract` | `MotoSwapFactoryAbi` | | Router | `IMotoswapRouterContract` | `MOTOSWAP_ROUTER_ABI` | | Pool | `IMotoswapPoolContract` | `MotoswapPoolAbi` | | Staking | `IMotoswapStakingContract` | `MOTOSWAP_STAKING_ABI` | | Native Swap | `INativeSwapContract` | `NativeSwapAbi` | | MOTO Token | `IMoto` | `MOTO_ABI` | --- ## Factory Contract ### IMotoswapFactoryContract Creates and manages liquidity pools. ```typescript import { MotoSwapFactoryAbi, IMotoswapFactoryContract, getContract, } from 'opnet'; const factory = getContract<IMotoswapFactoryContract>( factoryAddress, MotoSwapFactoryAbi, provider, network ); ``` ### Factory Methods | Method | Parameters | Returns | Description | |--------|------------|---------|-------------| | `getPool(tokenA, tokenB)` | `Address, Address` | `Address` | Get pool address | | `createPool(tokenA, tokenB)` | `Address, Address` | `Address` | Create new pool | | `allPools(index)` | `bigint` | `Address` | Get pool by index | | `allPoolsLength()` | - | `bigint` | Total pool count | ### Example: Get Pool Address ```typescript const pool = await factory.getPool(tokenA, tokenB); console.log('Pool address:', pool.properties.pool.toHex()); ``` --- ## Router Contract ### IMotoswapRouterContract Handles swaps and liquidity operations. ```typescript import { MOTOSWAP_ROUTER_ABI, IMotoswapRouterContract, getContract, } from 'opnet'; const router = getContract<IMotoswapRouterContract>( routerAddress, MOTOSWAP_ROUTER_ABI, provider, network ); ``` ### Router Methods | Method | Parameters | Description | |--------|------------|-------------| | `addLiquidity(...)` | Multiple | Add liquidity to pool | | `removeLiquidity(...)` | Multiple | Remove liquidity | | `swapExactTokensForTokens(...)` | Multiple | Swap exact input | | `swapTokensForExactTokens(...)` | Multiple | Swap for exact output | | `getAmountsOut(amountIn, path)` | `bigint, Address[]` | Quote output amounts | | `getAmountsIn(amountOut, path)` | `bigint, Address[]` | Quote input amounts | ### Example: Get Swap Quote ```typescript const amountIn = 1000000000n; // 10 tokens const path = [tokenA, tokenB]; const quote = await router.getAmountsOut(amountIn, path); console.log('Output amounts:', quote.properties.amounts); ``` ### Example: Execute Swap ```typescript const amountIn = 1000000000n; const amountOutMin = 900000000n; // 10% slippage const path = [tokenA, tokenB]; const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600); const result = await router.swapExactTokensForTokens( amountIn, amountOutMin, path, recipient, deadline, { signer: wallet.keypair, mldsaSigner: wallet.mldsaKeypair, refundTo: wallet.p2tr, feeRate: 10, } ); ``` --- ## Pool Contract ### IMotoswapPoolContract Represents a liquidity pool. ```typescript import { MotoswapPoolAbi, IMotoswapPoolContract, getContract, } from 'opnet'; const pool = getContract<IMotoswapPoolContract>( poolAddress, MotoswapPoolAbi, provider, network ); ``` ### Pool Methods | Method | Returns | Description | |--------|---------|-------------| | `token0()` | `Address` | First token | | `token1()` | `Address` | Second token | | `getReserves()` | `(bigint, bigint, bigint)` | Pool reserves | | `totalSupply()` | `bigint` | LP token supply | | `balanceOf(owner)` | `bigint` | LP token balance | | `price0CumulativeLast()` | `bigint` | Price accumulator | | `price1CumulativeLast()` | `bigint` | Price accumulator | ### Example: Get Pool Reserves ```typescript const reserves = await pool.getReserves(); console.log('Reserve 0:', reserves.properties.reserve0); console.log('Reserve 1:', reserves.properties.reserve1); console.log('Timestamp:', reserves.properties.blockTimestampLast); ``` --- ## Staking Contract ### IMotoswapStakingContract Handles MOTO token staking and rewards. ```typescript import { MOTOSWAP_STAKING_ABI, IMotoswapStakingContract, getContract, } from 'opnet'; const staking = getContract<IMotoswapStakingContract>( stakingAddress, MOTOSWAP_STAKING_ABI, provider, network ); ``` ### Staking Methods | Method | Parameters | Description | |--------|------------|-------------| | `stake(amount)` | `bigint` | Stake tokens | | `unstake(amount)` | `bigint` | Unstake tokens | | `claimRewards()` | - | Claim pending rewards | | `pendingRewards(user)` | `Address` | Get pending rewards | | `stakedBalance(user)` | `Address` | Get staked balance | --- ## Native Swap Contract ### INativeSwapContract Native BTC to token swap mechanism with liquidity provider queue system. > **⚠️ WARNING: Examples Are Simplified** > > The NativeSwap examples below are **incomplete and for demonstration purposes only**. They do NOT include: > > - **Reorg protection** - Bitcoin reorganizations can invalidate reservations > - **Confirmation tracking** - Waiting for sufficient confirmations before swapping > - **Error recovery** - Handling failed or stuck reservations > - **Race condition handling** - Multiple users competing for same liquidity > - **Timeout management** - Reservations expire and must be handled > > **Production implementations require significant additional logic to be user-safe.** These examples demonstrate the basic API usage only. Consult the OPNet team or review production implementations before deploying. ```typescript import { NativeSwapAbi, INativeSwapContract, getContract, } from 'opnet'; const nativeSwap = getContract<INativeSwapContract>( nativeSwapAddress, NativeSwapAbi, provider, network ); ``` ### Trading Methods | Method | Parameters | Description | |--------|------------|-------------| | `reserve(token, maximumAmountIn, minimumAmountOut, forLP, activationDelay)` | `Address, bigint, bigint, boolean, number` | Reserve tokens for swap | | `swap(token)` | `Address` | Execute swap after reservation | | `getQuote(token, satoshisIn)` | `Address, bigint` | Get swap quote | | `getReserve(token)` | `Address` | Get pool reserves | ### Liquidity Provider Methods | Method | Parameters | Description | |--------|------------|-------------| | `listLiquidity(token, receiver, receiverStr, amountIn, priority)` | `Address, Uint8Array, string, bigint, boolean` | List tokens for sale | | `cancelListing(token)` | `Address` | Cancel listing | | `withdrawListing(token)` | `Address` | Withdraw in emergency mode | | `getProviderDetails(token)` | `Address` | Get your provider info | | `getProviderDetailsById(providerId)` | `bigint` | Get provider by ID | | `getQueueDetails(token)` | `Address` | Get queue state | | `getPriorityQueueCost()` | - | Get priority queue fee | ### Pool Creation Methods | Method | Parameters | Description | |--------|------------|-------------| | `createPool(token, floorPrice, initialLiquidity, receiver, receiverStr, antiBotEnabledFor, antiBotMaximumTokensPerReservation, maxReservesIn5BlocksPercent, poolType, amplification, pegStalenessThreshold)` | Multiple | Create new liquidity pool | | `getPoolInfo(token)` | `Address` | Get pool type and settings | | `getAntibotSettings(token)` | `Address` | Get anti-bot config | ### Admin Methods | Method | Parameters | Description | |--------|------------|-------------| | `setFees(reservationBaseFee, priorityQueueBaseFee)` | `bigint, bigint` | Set fee parameters | | `setStakingContractAddress(address)` | `Address` | Set staking contract | | `setFeesAddress(address)` | `string` | Set fees collection address | | `pause()` | - | Pause contract | | `unpause()` | - | Unpause contract | | `activateWithdrawMode()` | - | Enable emergency withdrawals | | `isPaused()` | - | Check pause state | | `isWithdrawModeActive()` | - | Check withdraw mode | | `getFees()` | - | Get current fees | ### Native Swap Events ```typescript // Swap executed interface SwapExecutedEvent { buyer: Address; amountIn: bigint; amountOut: bigint; totalFees: bigint; } // Liquidity listed interface LiquidityListedEvent { totalLiquidity: bigint; provider: string; } // Reservation created interface ReservationCreatedEvent { expectedAmountOut: bigint; totalSatoshis: bigint; } // Provider fulfilled interface ProviderFulfilledEvent { providerId: bigint; removalCompleted: boolean; stakedAmount: bigint; } ``` ### Example: Get Quote and Reserve ```typescript import { INativeSwapContract, OPNetEvent, ReservationCreatedEvent, TransactionOutputFlags, TransactionParameters, } from 'opnet'; import { PsbtOutputExtended } from '@btc-vision/bitcoin'; // Fee recipient address (required for reservations) const FEE_RECIPIENT = 'bcrt1q...fee-address...'; // Get quote for 100,000 satoshis const token = Address.fromString('0x...token...'); const maximumAmountIn = 100_000n; const quote = await nativeSwap.getQuote(token, maximumAmountIn); console.log('Tokens out:', quote.properties.tokensOut); console.log('Required sats:', quote.properties.requiredSatoshis); console.log('Price:', quote.properties.price); // Calculate minimum output with 5% slippage const minimumAmountOut = quote.properties.tokensOut * 95n / 100n; // Create fee output (required) const feeOutput: PsbtOutputExtended = { address: FEE_RECIPIENT, value: 10_000, }; // Set transaction details with fee output nativeSwap.setTransactionDetails({ inputs: [], outputs: [ { to: feeOutput.address, value: BigInt(feeOutput.value), index: 1, scriptPubKey: undefined, flags: TransactionOutputFlags.hasTo, }, ], }); // Reserve tokens // Parameters: token, maximumAmountIn, minimumAmountOut, forLP, activationDelay const simulation = await nativeSwap.reserve( token, maximumAmountIn, minimumAmountOut, false, // forLP - set true if reserving for LP position 0, // activationDelay - blocks to wait before swap ); if (simulation.revert) { throw new Error(`Reservation failed: ${simulation.revert}`); } // Get reserved amount from event const event = simulation.events[ simulation.events.length - 1 ] as OPNetEvent<ReservationCreatedEvent>; console.log('Expected tokens out:', event.properties.expectedAmountOut); // Send transaction with fee output const params: TransactionParameters = { signer: wallet.keypair, mldsaSigner: wallet.mldsaKeypair, refundTo: wallet.address.p2tr(network), priorityFee: 0n, feeRate: 10, maximumAllowedSatToSpend: 10_000n, network: network, extraOutputs: [feeOutput], // Include fee output }; const result = await simulation.sendTransaction(params); console.log('Reserved:', result.transactionId); console.log('Tokens reserved:', event.properties.expectedAmountOut); ``` ### Example: Execute Swap After Reservation After reserving tokens, you must execute the swap by sending BTC to the liquidity providers. ```typescript import { INativeSwapContract, JSONRpcProvider, Swap, TransactionOutputFlags, TransactionParameters, } from 'opnet'; import { PsbtOutputExtended } from '@btc-vision/bitcoin'; interface Recipient { address: string; amount: bigint; } // Get recipients from reservation transaction async function getRecipients( provider: JSONRpcProvider, contract: INativeSwapContract, reservationTxId: string, ): Promise<Recipient[]> { const tx = await provider.getTransactionReceipt(reservationTxId); const decodedEvents = contract.decodeEvents(tx.events); return decodedEvents .filter((event) => event.type === 'LiquidityReserved') .map((event) => ({ amount: (event.properties as any).satoshisAmount, address: (event.properties as any).depositAddress, })); } // Execute swap async function executeSwap( provider: JSONRpcProvider, wallet: Wallet, contract: INativeSwapContract, token: Address, recipients: Recipient[], ): Promise<string> { // Build outputs for LP payments const outputs: PsbtOutputExtended[] = []; const transactionOutputs = []; const totalAmount = recipients.reduce((acc, r) => acc + r.amount, 0n); for (let i = 0; i < recipients.length; i++) { const recipient = recipients[i]; transactionOutputs.push({ to: recipient.address, value: recipient.amount, index: i + 1, flags: TransactionOutputFlags.hasTo, scriptPubKey: undefined, }); outputs.push({ address: recipient.address, value: Number(recipient.amount), }); } // Set transaction details with recipient outputs contract.setTransactionDetails({ inputs: [], outputs: transactionOutputs, }); // Execute swap const simulation: Swap = await contract.swap(token); if (simulation.revert) { throw new Error(`Swap failed: ${simulation.revert}`); } const params: TransactionParameters = { signer: wallet.keypair, mldsaSigner: wallet.mldsaKeypair, refundTo: wallet.address.p2tr(provider.getNetwork()), priorityFee: 0n, feeRate: 10, maximumAllowedSatToSpend: totalAmount + 10_000n, network: provider.getNetwork(), extraOutputs: outputs, // Include LP payment outputs }; const tx = await simulation.sendTransaction(params); return tx.transactionId; } // Usage const recipients = await getRecipients(provider, nativeSwap, reservationTxId); const swapTxId = await executeSwap(provider, wallet, nativeSwap, token, recipients); console.log('Swap executed:', swapTxId); ``` ### Example: List Liquidity ```typescript const token = Address.fromString('0x...token...'); const receiverPubKey = new Uint8Array(33); // 33 byte compressed pubkey const receiverAddress = 'bcrt1p...your-btc-address...'; const amount = 1_000_000_000_000n; // Amount to list const usePriorityQueue = true; const simulation = await nativeSwap.listLiquidity( token, receiverPubKey, receiverAddress, amount, usePriorityQueue, ); if (simulation.revert) { throw new Error(`List liquidity failed: ${simulation.revert}`); } const result = await simulation.sendTransaction({ signer: wallet.keypair, mldsaSigner: wallet.mldsaKeypair, refundTo: wallet.address.p2tr(network), maximumAllowedSatToSpend: 50_000n, network: network, feeRate: 10, }); console.log('Liquidity listed:', result.transactionId); ``` --- ## MOTO Token ### IMoto The native MOTO token interface. ```typescript import { MOTO_ABI, IMoto, getContract, } from 'opnet'; const moto = getContract<IMoto>( motoAddress, MOTO_ABI, provider, network ); ``` MOTO extends OP20 with additional staking-related functionality. --- ## Complete Swap Example ```typescript import { getContract, MOTOSWAP_ROUTER_ABI, IMotoswapRouterContract, OP_20_ABI, IOP20Contract, } from 'opnet'; async function executeSwap( provider: JSONRpcProvider, network: Network, routerAddress: string, tokenIn: string, tokenOut: string, amountIn: bigint, slippagePercent: number, wallet: Wallet ): Promise<void> { // Get router const router = getContract<IMotoswapRouterContract>( routerAddress, MOTOSWAP_ROUTER_ABI, provider, network ); // Get token contract for approval const tokenInContract = getContract<IOP20Contract>( tokenIn, OP_20_ABI, provider, network ); // Approve router await tokenInContract.increaseAllowance( Address.fromString(routerAddress), amountIn, { signer: wallet.keypair, mldsaSigner: wallet.mldsaKeypair, refundTo: wallet.p2tr, feeRate: 10, } ); // Get quote const path = [ Address.fromString(tokenIn), Address.fromString(tokenOut), ]; const quote = await router.getAmountsOut(amountIn, path); const expectedOut = quote.properties.amounts[1]; // Calculate minimum output const slippageMultiplier = BigInt(100 - slippagePercent); const amountOutMin = (expectedOut * slippageMultiplier) / 100n; // Execute swap const deadline = BigInt(Math.floor(Date.now() / 1000) + 3600); const result = await router.swapExactTokensForTokens( amountIn, amountOutMin, path, wallet.address, deadline, { signer: wallet.keypair, mldsaSigner: wallet.mldsaKeypair, refundTo: wallet.p2tr, feeRate: 10, } ); console.log('Swap completed:', result.success); } ``` --- ## Best Practices 1. **Check Slippage**: Always set reasonable slippage tolerance 2. **Approve First**: Ensure token approval before swaps 3. **Set Deadline**: Use reasonable deadline for transactions 4. **Check Reserves**: Verify pool has sufficient liquidity 5. **Monitor Prices**: Check price impact before large swaps --- ## Next Steps - [Factory ABIs](./factory-abis.md) - Token factories - [Stablecoin ABIs](./stablecoin-abis.md) - Stablecoin interfaces - [Advanced Swaps](../examples/advanced-swaps.md) - Swap examples --- [ Previous: OP721 ABI](./op721-abi.md) | [Next: Factory ABIs ](./factory-abis.md)