diff --git a/packages/evm-contracts/contracts/lvr_amm/LvrMarket.sol b/packages/evm-contracts/contracts/lvr_amm/LvrMarket.sol index 904a7378..665a3f33 100644 --- a/packages/evm-contracts/contracts/lvr_amm/LvrMarket.sol +++ b/packages/evm-contracts/contracts/lvr_amm/LvrMarket.sol @@ -20,12 +20,12 @@ contract LvrMarket is ReentrancyGuard { using SafeCast for uint256; event MarketInitialized(uint256 liquidity, uint256 collateralIn, uint256 timestamp); - + event OutcomeProposed(uint256 outcome, address indexed proposer, uint256 resolutionTimestamp); event MarketDisputed(); event MarketSettled(uint256 outcome, address indexed proposer, uint256 bondReturned); event MarketResolvedByAdmin(uint256 outcome, address indexed admin); - + event MarketBuy(address indexed buyer, bool isBuyYes, uint256 amountIn, uint256 amountOut); event MarketSell(address indexed seller, bool isSellYes, uint256 amountIn, uint256 amountOut); event CollateralRedeemed(address indexed redeemer, uint256 amountYes, uint256 amountNo, uint256 payout); @@ -132,10 +132,10 @@ contract LvrMarket is ReentrancyGuard { function dispute() external isRouter nonReentrant { require(state == MarketState.PENDING, "Challenge Window Not opened"); - // Break the bond + // Break the bond state = MarketState.DISPUTED; // set the market outcome through creator/resolver voting/admin - + emit MarketDisputed(); } @@ -189,13 +189,15 @@ contract LvrMarket is ReentrancyGuard { outcome = duel.winner == DuelOutcomeOracle.Side.A ? 0 : 1; } - // Settle bond: slash if proposer was wrong or market was cancelled + // Settle bond: return if proposer was correct or market cancelled; slash if wrong uint256 returnedBond = 0; if (proposer != address(0)) { - if (state == MarketState.PENDING && outcome == proposedOutcome) { + if (outcome == proposedOutcome || outcome == 2) { + // Proposer was correct, or market cancelled — return bond IERC20(collateralToken).safeTransfer(proposer, bondValue); returnedBond = bondValue; } else { + // Proposer was wrong — slash to treasury IERC20(collateralToken).safeTransfer(treasuryAddress, bondValue); } } @@ -228,7 +230,8 @@ contract LvrMarket is ReentrancyGuard { // Cancellation: each token redeems at 0.5 collateral to maintain solvency. // Paying 1:1 for both tokens would exceed collateral pool since // total_yes_supply + total_no_supply > total_collateral after fee burns. - payout = (amountYesIn + amountNoIn) / 2; + // Intentional: rounds down (loses at most 1 wei) to guarantee solvency. + payout = amountYesIn / 2 + amountNoIn / 2; IERC20(collateralToken).safeTransfer(redeemer, payout); } else { revert("Invalid outcome"); @@ -243,7 +246,7 @@ contract LvrMarket is ReentrancyGuard { noToken = new NoToken(address(this), collateralIn); liquidity = Math.calcInitialLiquidity(collateralIn); liquidityInitialized = true; - + emit MarketInitialized(liquidity, collateralIn, block.timestamp); return liquidity; } @@ -340,7 +343,7 @@ contract LvrMarket is ReentrancyGuard { } function getPriceYes() public view returns(uint256) { - if (isDynamic && block.timestamp >= deadline) return 0.5e18; // neutral price after deadline + if (block.timestamp >= deadline) return 0.5e18; // neutral price after deadline (market expired) uint256 liq = isDynamic ? Math.calcLiquidity(liquidity, deadline, block.timestamp) : liquidity; return Math.calcPrice(yesToken.balanceOf(address(this)), noToken.balanceOf(address(this)), liq); } diff --git a/packages/evm-contracts/contracts/lvr_amm/Router.sol b/packages/evm-contracts/contracts/lvr_amm/Router.sol index 9d0fd7ae..751ec701 100644 --- a/packages/evm-contracts/contracts/lvr_amm/Router.sol +++ b/packages/evm-contracts/contracts/lvr_amm/Router.sol @@ -100,12 +100,14 @@ contract Router is AccessControl, ReentrancyGuard, IMarketBuyCallback, IMarketSe LvrMarket market = new LvrMarket(address(this), duelKey, address(duelOracle), isDynamic, duration, address(mUSD), msg.sender, treasury, feeBps); - allowedMarkets[address(market)] = true; // Transfer USD token to market contract mUSD.safeTransferFrom(msg.sender, address(market), collateralIn); uint256 liquidity = market.initializeLiquidity(collateralIn); + // Add to allowlist AFTER successful initialization to prevent callbacks to uninitialized markets + allowedMarkets[address(market)] = true; + markets[marketId] = MarketInfo({ market: address(market), liquidity: liquidity, diff --git a/packages/hyperbet-avax/keeper/src/idl/lvr_amm.json b/packages/hyperbet-avax/keeper/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/hyperbet-avax/keeper/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/hyperbet-avax/keeper/src/idl/lvr_amm.ts b/packages/hyperbet-avax/keeper/src/idl/lvr_amm.ts new file mode 100644 index 00000000..3c7503d8 --- /dev/null +++ b/packages/hyperbet-avax/keeper/src/idl/lvr_amm.ts @@ -0,0 +1,2147 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/lvr_amm.json`. + */ +export type LvrAmm = { + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvrAmm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "lvrAmm" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "createBetAccount", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "expirationAt", + "type": "i64" + } + ] + }, + { + "name": "freezeConfig", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "getPrice", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "initBetAccount", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "adminState", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initializeConfig", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasuryYesAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasuryNoAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "setPaused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settleBet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "adminState", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "duelState", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "sideWon", + "type": "u8" + } + ] + }, + { + "name": "withdrawPostSettle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "ammConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "adminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "ammConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "ammConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "ammPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "canOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "outComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "invalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "quantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "signerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "notEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "notEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "adminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "signerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "betAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "betNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "betNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "betNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "invalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "oracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "mathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "invalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "feeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "marketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "configFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "invalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "missingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "invalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "adminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "ammConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + }, + { + "name": "configFrozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "ammConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "ammConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + }, + { + "name": "ammPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "isInitialized", + "type": "bool" + }, + { + "name": "sideWon", + "type": { + "option": "u8" + } + }, + { + "name": "expirationAt", + "type": "i64" + }, + { + "name": "createdAt", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + } + ] +}; diff --git a/packages/hyperbet-bsc/app/src/idl/lvr_amm.json b/packages/hyperbet-bsc/app/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/hyperbet-bsc/app/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/hyperbet-bsc/app/src/idl/lvr_amm.ts b/packages/hyperbet-bsc/app/src/idl/lvr_amm.ts new file mode 100644 index 00000000..3c7503d8 --- /dev/null +++ b/packages/hyperbet-bsc/app/src/idl/lvr_amm.ts @@ -0,0 +1,2147 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/lvr_amm.json`. + */ +export type LvrAmm = { + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvrAmm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "lvrAmm" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "createBetAccount", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "expirationAt", + "type": "i64" + } + ] + }, + { + "name": "freezeConfig", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "getPrice", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "initBetAccount", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "adminState", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initializeConfig", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasuryYesAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasuryNoAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "setPaused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settleBet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "adminState", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "duelState", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "sideWon", + "type": "u8" + } + ] + }, + { + "name": "withdrawPostSettle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "ammConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "adminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "ammConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "ammConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "ammPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "canOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "outComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "invalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "quantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "signerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "notEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "notEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "adminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "signerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "betAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "betNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "betNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "betNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "invalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "oracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "mathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "invalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "feeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "marketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "configFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "invalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "missingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "invalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "adminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "ammConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + }, + { + "name": "configFrozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "ammConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "ammConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + }, + { + "name": "ammPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "isInitialized", + "type": "bool" + }, + { + "name": "sideWon", + "type": { + "option": "u8" + } + }, + { + "name": "expirationAt", + "type": "i64" + }, + { + "name": "createdAt", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + } + ] +}; diff --git a/packages/hyperbet-bsc/app/src/lib/config.ts b/packages/hyperbet-bsc/app/src/lib/config.ts index d2a4f54e..e76edcdc 100644 --- a/packages/hyperbet-bsc/app/src/lib/config.ts +++ b/packages/hyperbet-bsc/app/src/lib/config.ts @@ -188,14 +188,17 @@ function buildEvmConfig( | "bscRpcUrl" | "bscChainId" | "bscGoldClobAddress" + | "bscGoldAmmRouterAddress" | "bscGoldTokenAddress" | "baseRpcUrl" | "baseChainId" | "baseGoldClobAddress" + | "baseGoldAmmRouterAddress" | "baseGoldTokenAddress" | "avaxRpcUrl" | "avaxChainId" | "avaxGoldClobAddress" + | "avaxGoldAmmRouterAddress" | "avaxGoldTokenAddress" > { const defaults = resolveBettingEvmDefaults( @@ -205,15 +208,18 @@ function buildEvmConfig( bscRpcUrl: defaultRpcUrlForEvmNetwork(defaults.bsc.networkKey), bscChainId: defaults.bsc.chainId, bscGoldClobAddress: defaults.bsc.goldClobAddress, + bscGoldAmmRouterAddress: defaults.bsc.goldAmmRouterAddress, bscGoldTokenAddress: defaults.bsc.goldTokenAddress, baseRpcUrl: defaultRpcUrlForEvmNetwork(defaults.base.networkKey), baseChainId: defaults.base.chainId, baseGoldClobAddress: defaults.base.goldClobAddress, + baseGoldAmmRouterAddress: defaults.base.goldAmmRouterAddress, baseGoldTokenAddress: defaults.base.goldTokenAddress, avaxRpcUrl: defaultAvaxRpcUrlForEnvironment(environment), avaxChainId: defaultAvaxChainIdForEnvironment(environment), - avaxGoldClobAddress: "", - avaxGoldTokenAddress: "", + avaxGoldClobAddress: defaults.avax.goldClobAddress, + avaxGoldAmmRouterAddress: defaults.avax.goldAmmRouterAddress, + avaxGoldTokenAddress: defaults.avax.goldTokenAddress, }; } @@ -251,14 +257,17 @@ interface EnvConfig { bscRpcUrl: string; bscChainId: number; bscGoldClobAddress: string; + bscGoldAmmRouterAddress: string; bscGoldTokenAddress: string; baseRpcUrl: string; baseChainId: number; baseGoldClobAddress: string; + baseGoldAmmRouterAddress: string; baseGoldTokenAddress: string; avaxRpcUrl: string; avaxChainId: number; avaxGoldClobAddress: string; + avaxGoldAmmRouterAddress: string; avaxGoldTokenAddress: string; walletConnectProjectId: string; diff --git a/packages/hyperbet-bsc/keeper/src/idl/lvr_amm.json b/packages/hyperbet-bsc/keeper/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/hyperbet-bsc/keeper/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/hyperbet-bsc/keeper/src/idl/lvr_amm.ts b/packages/hyperbet-bsc/keeper/src/idl/lvr_amm.ts new file mode 100644 index 00000000..3c7503d8 --- /dev/null +++ b/packages/hyperbet-bsc/keeper/src/idl/lvr_amm.ts @@ -0,0 +1,2147 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/lvr_amm.json`. + */ +export type LvrAmm = { + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvrAmm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "lvrAmm" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "createBetAccount", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "expirationAt", + "type": "i64" + } + ] + }, + { + "name": "freezeConfig", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "getPrice", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "initBetAccount", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "adminState", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initializeConfig", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasuryYesAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasuryNoAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "setPaused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settleBet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "adminState", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "duelState", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "sideWon", + "type": "u8" + } + ] + }, + { + "name": "withdrawPostSettle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "ammConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "adminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "ammConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "ammConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "ammPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "canOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "outComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "invalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "quantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "signerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "notEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "notEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "adminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "signerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "betAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "betNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "betNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "betNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "invalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "oracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "mathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "invalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "feeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "marketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "configFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "invalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "missingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "invalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "adminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "ammConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + }, + { + "name": "configFrozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "ammConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "ammConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + }, + { + "name": "ammPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "isInitialized", + "type": "bool" + }, + { + "name": "sideWon", + "type": { + "option": "u8" + } + }, + { + "name": "expirationAt", + "type": "i64" + }, + { + "name": "createdAt", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + } + ] +}; diff --git a/packages/hyperbet-chain-registry/src/index.ts b/packages/hyperbet-chain-registry/src/index.ts index 7bf5b29c..2afe410b 100644 --- a/packages/hyperbet-chain-registry/src/index.ts +++ b/packages/hyperbet-chain-registry/src/index.ts @@ -42,6 +42,7 @@ export const PREDICTION_MARKET_RESERVED_METADATA_KEYS = [ "cancellationReason", ] as const; export type PredictionMarketWinner = "NONE" | "A" | "B"; +export type PredictionMarketType = "clob" | "amm"; export type PredictionMarketReservedMetadataKey = (typeof PREDICTION_MARKET_RESERVED_METADATA_KEYS)[number]; @@ -62,6 +63,7 @@ export interface NativeCurrencyConfig { export interface ChainFeatureFlags { predictionMarkets: boolean; perps: boolean; + amm: boolean; } export interface BettingSolanaDeployment { @@ -69,6 +71,7 @@ export interface BettingSolanaDeployment { fightOracleProgramId: string; goldClobMarketProgramId: string; goldPerpsMarketProgramId: string; + goldAmmMarketProgramId: string; goldMint: string; usdcMint: string; } @@ -88,6 +91,8 @@ export interface BettingEvmDeployment { rpcEnvVar: string; duelOracleAddress: string; goldClobAddress: string; + goldAmmRouterAddress: string; + mUsdTokenAddress: string; adminAddress: string; marketOperatorAddress: string; treasuryAddress: string; @@ -157,6 +162,8 @@ export interface ResolvedBettingEvmRuntimeEnv { rpcUrl: string; duelOracleAddress: string; goldClobAddress: string; + goldAmmRouterAddress: string; + mUsdTokenAddress: string; } export interface ExternalBetRecordPayload { @@ -190,6 +197,7 @@ export interface PredictionMarketLifecycleRecord { txRef: string | null; syncedAt: number | null; metadata?: PredictionMarketLifecycleMetadata; + marketType?: PredictionMarketType; } export const BETTING_SOLANA_CLUSTERS: BettingSolanaCluster[] = [ @@ -217,6 +225,7 @@ export const BETTING_EVM_CHAIN_ORDER: BettingEvmChain[] = [ const DEFAULT_FEATURE_FLAGS: ChainFeatureFlags = { predictionMarkets: true, perps: false, + amm: false, }; const SOLANA_DEPLOYMENTS: Record = @@ -226,6 +235,7 @@ const SOLANA_DEPLOYMENTS: Record fightOracleProgramId: "B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo", goldClobMarketProgramId: "DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf", goldPerpsMarketProgramId: "EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT", + goldAmmMarketProgramId: "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", goldMint: "DK9nBUMfdu4XprPRWeh8f6KnQiGWD8Z4xz3yzs9gpump", usdcMint: "", }, @@ -234,6 +244,7 @@ const SOLANA_DEPLOYMENTS: Record fightOracleProgramId: "B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo", goldClobMarketProgramId: "DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf", goldPerpsMarketProgramId: "EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT", + goldAmmMarketProgramId: "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", goldMint: "DK9nBUMfdu4XprPRWeh8f6KnQiGWD8Z4xz3yzs9gpump", usdcMint: "", }, @@ -242,6 +253,7 @@ const SOLANA_DEPLOYMENTS: Record fightOracleProgramId: "B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo", goldClobMarketProgramId: "DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf", goldPerpsMarketProgramId: "EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT", + goldAmmMarketProgramId: "", goldMint: "", usdcMint: "", }, @@ -250,6 +262,7 @@ const SOLANA_DEPLOYMENTS: Record fightOracleProgramId: "B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo", goldClobMarketProgramId: "DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf", goldPerpsMarketProgramId: "EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT", + goldAmmMarketProgramId: "", goldMint: "DK9nBUMfdu4XprPRWeh8f6KnQiGWD8Z4xz3yzs9gpump", usdcMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", }, @@ -265,6 +278,8 @@ const EVM_DEPLOYMENTS: Record = { rpcEnvVar: "BSC_TESTNET_RPC", duelOracleAddress: "0xAd13D36b02f0F6C44d508824Ae9D407931D91f91", goldClobAddress: "0x067335E0b1F226a8e345a289B3b93Ed5377d636e", + goldAmmRouterAddress: "", + mUsdTokenAddress: "", adminAddress: "0x7908b93DF1A91A5e1B83a4538107Db3c9131eED8", marketOperatorAddress: "0x99622633cF1e476C8bD9161f5B9d4F290a1D2Ea1", treasuryAddress: "0x5c5A3554F12875aBB63a6b8027b9A23C423F5C84", @@ -294,6 +309,8 @@ const EVM_DEPLOYMENTS: Record = { rpcEnvVar: "BSC_MAINNET_RPC", duelOracleAddress: "0x8F582bc1D34Ca6dA12ac46B7c7Fdec02f2465961", goldClobAddress: "0x443C09B1E7bb7bA3392b02500772B185654A6F33", + goldAmmRouterAddress: "", + mUsdTokenAddress: "", adminAddress: "0x7908b93DF1A91A5e1B83a4538107Db3c9131eED8", marketOperatorAddress: "0x7908b93DF1A91A5e1B83a4538107Db3c9131eED8", treasuryAddress: "0x0262dC245f38d614d508D8BD680c69E3B6D26F4c", @@ -323,6 +340,8 @@ const EVM_DEPLOYMENTS: Record = { rpcEnvVar: "BASE_SEPOLIA_RPC", duelOracleAddress: "", goldClobAddress: "", + goldAmmRouterAddress: "", + mUsdTokenAddress: "", adminAddress: "", marketOperatorAddress: "", treasuryAddress: "", @@ -352,6 +371,8 @@ const EVM_DEPLOYMENTS: Record = { rpcEnvVar: "BASE_MAINNET_RPC", duelOracleAddress: "0x63BF7f48A2795832C2b5f78172A1C6BE655F3a72", goldClobAddress: "0xb8c66D6895Bafd1B0027F2c0865865043064437C", + goldAmmRouterAddress: "", + mUsdTokenAddress: "", adminAddress: "0x7908b93DF1A91A5e1B83a4538107Db3c9131eED8", marketOperatorAddress: "0x7908b93DF1A91A5e1B83a4538107Db3c9131eED8", treasuryAddress: "0x0262dC245f38d614d508D8BD680c69E3B6D26F4c", @@ -381,6 +402,8 @@ const EVM_DEPLOYMENTS: Record = { rpcEnvVar: "AVAX_FUJI_RPC", duelOracleAddress: "0xAd13D36b02f0F6C44d508824Ae9D407931D91f91", goldClobAddress: "0x067335E0b1F226a8e345a289B3b93Ed5377d636e", + goldAmmRouterAddress: "", + mUsdTokenAddress: "", adminAddress: "0x7908b93DF1A91A5e1B83a4538107Db3c9131eED8", marketOperatorAddress: "0x99622633cF1e476C8bD9161f5B9d4F290a1D2Ea1", treasuryAddress: "0x5c5A3554F12875aBB63a6b8027b9A23C423F5C84", @@ -410,6 +433,8 @@ const EVM_DEPLOYMENTS: Record = { rpcEnvVar: "AVAX_MAINNET_RPC", duelOracleAddress: "", goldClobAddress: "", + goldAmmRouterAddress: "", + mUsdTokenAddress: "", adminAddress: "", marketOperatorAddress: "", treasuryAddress: "", @@ -608,6 +633,16 @@ export function resolveBettingEvmRuntimeEnv( `CLOB_CONTRACT_ADDRESS_${chainUpper}`, `${chainUpper}_GOLD_CLOB_ADDRESS`, ]) ?? deployment.goldClobAddress, + goldAmmRouterAddress: + firstNonEmptyEnvValue(env, [ + `AMM_ROUTER_ADDRESS_${chainUpper}`, + `${chainUpper}_GOLD_AMM_ROUTER_ADDRESS`, + ]) ?? deployment.goldAmmRouterAddress, + mUsdTokenAddress: + firstNonEmptyEnvValue(env, [ + `MUSD_TOKEN_ADDRESS_${chainUpper}`, + `${chainUpper}_MUSD_TOKEN_ADDRESS`, + ]) ?? deployment.mUsdTokenAddress, }; } @@ -797,6 +832,9 @@ export function normalizePredictionMarketLifecycleRecord( txRef: typeof candidate.txRef === "string" ? candidate.txRef : null, syncedAt: normalizePredictionMarketTimestamp(candidate.syncedAt), metadata: normalizePredictionMarketLifecycleMetadata(candidate.metadata), + ...(candidate.marketType === "amm" || candidate.marketType === "clob" + ? { marketType: candidate.marketType } + : {}), }; } diff --git a/packages/hyperbet-evm/keeper/src/idl/lvr_amm.json b/packages/hyperbet-evm/keeper/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/hyperbet-evm/keeper/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/hyperbet-evm/keeper/src/idl/lvr_amm.ts b/packages/hyperbet-evm/keeper/src/idl/lvr_amm.ts new file mode 100644 index 00000000..3c7503d8 --- /dev/null +++ b/packages/hyperbet-evm/keeper/src/idl/lvr_amm.ts @@ -0,0 +1,2147 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/lvr_amm.json`. + */ +export type LvrAmm = { + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvrAmm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "lvrAmm" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "createBetAccount", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "expirationAt", + "type": "i64" + } + ] + }, + { + "name": "freezeConfig", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "getPrice", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "initBetAccount", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "adminState", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initializeConfig", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasuryYesAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasuryNoAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "setPaused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settleBet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "adminState", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "duelState", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "sideWon", + "type": "u8" + } + ] + }, + { + "name": "withdrawPostSettle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "ammConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "adminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "ammConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "ammConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "ammPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "canOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "outComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "invalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "quantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "signerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "notEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "notEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "adminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "signerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "betAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "betNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "betNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "betNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "invalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "oracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "mathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "invalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "feeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "marketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "configFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "invalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "missingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "invalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "adminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "ammConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + }, + { + "name": "configFrozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "ammConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "ammConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + }, + { + "name": "ammPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "isInitialized", + "type": "bool" + }, + { + "name": "sideWon", + "type": { + "option": "u8" + } + }, + { + "name": "expirationAt", + "type": "i64" + }, + { + "name": "createdAt", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + } + ] +}; diff --git a/packages/hyperbet-mm-core/src/index.ts b/packages/hyperbet-mm-core/src/index.ts index c606f17d..1cd66408 100644 --- a/packages/hyperbet-mm-core/src/index.ts +++ b/packages/hyperbet-mm-core/src/index.ts @@ -670,3 +670,173 @@ export function evaluateQuoteDecision( reason: null, }; } + +// === AMM Market-Making Logic === + +export interface AmmMarketSnapshot { + chainKey: BettingChainKey; + lifecycleStatus: PredictionMarketLifecycleStatus; + duelKey: string | null; + marketRef: string | null; + /** YES price as probability [0, 1] */ + ammPriceYes: number; + reserveYes: number; + reserveNo: number; + liquidity: number; + betCloseTimeMs?: number | null; + lastStreamAtMs?: number | null; + lastOracleAtMs?: number | null; + lastRpcAtMs?: number | null; + exposure: MarketExposure; +} + +export interface AmmTradeDecision { + action: "buy_yes" | "buy_no" | "sell_yes" | "sell_no" | "hold"; + /** Collateral amount (buy) or token amount (sell) */ + amount: number; + /** Fair value probability [0, 1] */ + fairValue: number; + /** Current AMM price [0, 1] */ + ammPrice: number; + /** Absolute deviation in basis points */ + deviationBps: number; + risk: RiskState; + reason: string | null; +} + +export interface AmmMarketMakerConfig { + /** Min deviation from fair value to trigger trade (bps) */ + deviationThresholdBps: number; + /** Max collateral per trade */ + maxTradeSize: number; + /** Min trade size */ + minTradeSize: number; + /** Max total yes+no token holdings */ + maxPositionSize: number; + /** Inventory imbalance trigger for rebalancing (bps) */ + rebalanceThresholdBps: number; + /** Max drawdown before halting (bps) */ + maxDrawdownBps: number; + /** Stale stream threshold (ms) */ + staleStreamAfterMs: number; + /** Stale oracle threshold (ms) */ + staleOracleAfterMs: number; + /** Stale RPC threshold (ms) */ + staleRpcAfterMs: number; + /** Guard window before bet close (ms) */ + betCloseGuardMs: number; + /** Max slippage tolerance for AMM trades (bps, default 200 = 2%) */ + maxSlippageBps: number; +} + +export const DEFAULT_AMM_MARKET_MAKER_CONFIG: AmmMarketMakerConfig = { + deviationThresholdBps: 300, + maxTradeSize: 100_000, + minTradeSize: 10_000, + maxPositionSize: 500_000, + rebalanceThresholdBps: 1_000, + maxDrawdownBps: 2_000, + staleStreamAfterMs: 3_000, + staleOracleAfterMs: 5_000, + staleRpcAfterMs: 5_000, + betCloseGuardMs: 5_000, + maxSlippageBps: 200, +}; + +export function buildAmmTradeDecision( + snapshot: AmmMarketSnapshot, + signal: Pick = {}, + config: AmmMarketMakerConfig = DEFAULT_AMM_MARKET_MAKER_CONFIG, + now = Date.now(), +): AmmTradeDecision { + // Build risk state using a synthetic MarketSnapshot for gate reuse + const syntheticSnapshot: MarketSnapshot = { + chainKey: snapshot.chainKey, + lifecycleStatus: snapshot.lifecycleStatus, + duelKey: snapshot.duelKey, + marketRef: snapshot.marketRef, + bestBid: null, + bestAsk: null, + betCloseTimeMs: snapshot.betCloseTimeMs, + lastStreamAtMs: snapshot.lastStreamAtMs, + lastOracleAtMs: snapshot.lastOracleAtMs, + lastRpcAtMs: snapshot.lastRpcAtMs, + exposure: snapshot.exposure, + }; + const syntheticConfig: MarketMakerConfig = { + ...DEFAULT_MARKET_MAKER_CONFIG, + maxDrawdownBps: config.maxDrawdownBps, + staleStreamAfterMs: config.staleStreamAfterMs, + staleOracleAfterMs: config.staleOracleAfterMs, + staleRpcAfterMs: config.staleRpcAfterMs, + betCloseGuardMs: config.betCloseGuardMs, + }; + const risk = buildRiskState(syntheticSnapshot, syntheticConfig, now); + + // Compute fair value: signal in [1,999] CLOB ticks → normalize to [0,1] + const clobFairValue = computeFairValue({ + signalPrice: signal.signalPrice, + signalWeight: signal.signalWeight, + fallbackPrice: 500, + inventorySkew: computeInventorySkew(snapshot.exposure), + inventorySkewBps: DEFAULT_MARKET_MAKER_CONFIG.inventorySkewBps, + }); + const fairValue = clobFairValue / 1000; // [0, 1] + + const ammPrice = snapshot.ammPriceYes; + const deviation = ammPrice - fairValue; + const deviationBps = Math.round(Math.abs(deviation) * 10_000); + + const hold = (reason: string | null): AmmTradeDecision => ({ + action: "hold", + amount: 0, + fairValue, + ammPrice, + deviationBps, + risk, + reason, + }); + + // Circuit breaker + if (risk.circuitBreaker.active) { + return hold(risk.circuitBreaker.reason); + } + + // Below deviation threshold — hold + if (deviationBps < config.deviationThresholdBps) { + return hold("within-threshold"); + } + + // Position limit check + const totalPosition = + snapshot.exposure.yes + snapshot.exposure.no + + snapshot.exposure.openYes + snapshot.exposure.openNo; + if (totalPosition >= config.maxPositionSize) { + return hold("position-limit"); + } + + // Size proportional to deviation, clamped + const deviationRatio = Math.min(1, deviationBps / 10_000); + const headroom = Math.max(0, config.maxPositionSize - totalPosition); + const rawSize = Math.round(config.maxTradeSize * deviationRatio); + const tradeSize = Math.min(rawSize, headroom, config.maxTradeSize); + + if (tradeSize < config.minTradeSize) { + return hold("below-min-size"); + } + + // AMM price < fair value → YES is underpriced → buy YES + // AMM price > fair value → YES is overpriced → buy NO + const action: AmmTradeDecision["action"] = + deviation < 0 ? "buy_yes" : "buy_no"; + + return { + action, + amount: tradeSize, + fairValue, + ammPrice, + deviationBps, + risk, + reason: `deviation-${deviationBps}bps`, + }; +} diff --git a/packages/hyperbet-solana/anchor/Anchor.toml b/packages/hyperbet-solana/anchor/Anchor.toml index 46c32f1f..7d0e7bb2 100644 --- a/packages/hyperbet-solana/anchor/Anchor.toml +++ b/packages/hyperbet-solana/anchor/Anchor.toml @@ -9,16 +9,19 @@ skip-lint = false fight_oracle = "B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo" gold_clob_market = "DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf" gold_perps_market = "EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT" +lvr_amm = "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5" [programs.localnet] fight_oracle = "B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo" gold_clob_market = "DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf" gold_perps_market = "EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT" +lvr_amm = "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5" [programs.mainnet] fight_oracle = "B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo" gold_clob_market = "DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf" gold_perps_market = "EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT" +lvr_amm = "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5" [registry] url = "https://api.apr.dev" diff --git a/packages/hyperbet-solana/anchor/Cargo.lock b/packages/hyperbet-solana/anchor/Cargo.lock index 73f6bcf4..8e43fd65 100644 --- a/packages/hyperbet-solana/anchor/Cargo.lock +++ b/packages/hyperbet-solana/anchor/Cargo.lock @@ -4,30 +4,30 @@ version = 4 [[package]] name = "aead" -version = "0.4.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ + "crypto-common", "generic-array", ] [[package]] name = "aes" -version = "0.7.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", "cpufeatures", - "opaque-debug", ] [[package]] name = "aes-gcm-siv" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" dependencies = [ "aead", "aes", @@ -38,17 +38,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.17", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.12" @@ -76,38 +65,13 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "anchor-attribute-access-control" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47fe28365b33e8334dd70ae2f34a43892363012fe239cf37d2ee91693575b1f8" -dependencies = [ - "anchor-syn 0.30.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "anchor-attribute-access-control" version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a883ca44ef14b2113615fc6d3a85fefc68b5002034e88db37f7f1f802f88aa9" dependencies = [ - "anchor-syn 0.32.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-account" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c288d496168268d198d9b53ee9f4f9d260a55ba4df9877ea1d4486ad6109e0f" -dependencies = [ - "anchor-syn 0.30.1", - "bs58 0.5.1", + "anchor-syn", "proc-macro2", "quote", "syn 1.0.109", @@ -119,42 +83,20 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c4d97763b29030412b4b80715076377edc9cc63bc3c9e667297778384b9fd2" dependencies = [ - "anchor-syn 0.32.1", - "bs58 0.5.1", + "anchor-syn", + "bs58", "proc-macro2", "quote", "syn 1.0.109", ] -[[package]] -name = "anchor-attribute-constant" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b77b6948d0eeaaa129ce79eea5bbbb9937375a9241d909ca8fb9e006bb6e90" -dependencies = [ - "anchor-syn 0.30.1", - "quote", - "syn 1.0.109", -] - [[package]] name = "anchor-attribute-constant" version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae3328bbf9bbd517a51621b1ba6cbec06cbbc25e8cfc7403bddf69bcf088206" dependencies = [ - "anchor-syn 0.32.1", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-error" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d20bb569c5a557c86101b944721d865e1fd0a4c67c381d31a44a84f07f84828" -dependencies = [ - "anchor-syn 0.30.1", + "anchor-syn", "quote", "syn 1.0.109", ] @@ -165,19 +107,7 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf2398a6d9e16df1ee9d7d37d970a8246756de898c8dd16ef6bdbe4da20cf39a" dependencies = [ - "anchor-syn 0.32.1", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-event" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cebd8d0671a3a9dc3160c48598d652c34c77de6be4d44345b8b514323284d57" -dependencies = [ - "anchor-syn 0.30.1", - "proc-macro2", + "anchor-syn", "quote", "syn 1.0.109", ] @@ -188,26 +118,9 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f12758f4ec2f0e98d4d56916c6fe95cb23d74b8723dd902c762c5ef46ebe7b65" dependencies = [ - "anchor-syn 0.32.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-attribute-program" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb2a5eb0860e661ab31aff7bb5e0288357b176380e985bade4ccb395981b42d" -dependencies = [ - "anchor-lang-idl", - "anchor-syn 0.30.1", - "anyhow", - "bs58 0.5.1", - "heck", + "anchor-syn", "proc-macro2", "quote", - "serde_json", "syn 1.0.109", ] @@ -218,9 +131,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c7193b5af2649813584aae6e3569c46fd59616a96af2083c556b13136c3830f" dependencies = [ "anchor-lang-idl", - "anchor-syn 0.32.1", + "anchor-syn", "anyhow", - "bs58 0.5.1", + "bs58", "heck", "proc-macro2", "quote", @@ -228,37 +141,13 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "anchor-derive-accounts" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04368b5abef4266250ca8d1d12f4dff860242681e4ec22b885dcfe354fd35aa1" -dependencies = [ - "anchor-syn 0.30.1", - "quote", - "syn 1.0.109", -] - [[package]] name = "anchor-derive-accounts" version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d332d1a13c0fca1a446de140b656e66110a5e8406977dcb6a41e5d6f323760b0" dependencies = [ - "anchor-syn 0.32.1", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-derive-serde" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0bb0e0911ad4a70cab880cdd6287fe1e880a1a9d8e4e6defa8e9044b9796a6c" -dependencies = [ - "anchor-syn 0.30.1", - "borsh-derive-internal 0.10.4", - "proc-macro2", + "anchor-syn", "quote", "syn 1.0.109", ] @@ -269,19 +158,8 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8656e4af182edaeae665fa2d2d7ee81148518b5bd0be9a67f2a381bb17da7d46" dependencies = [ - "anchor-syn 0.32.1", - "borsh-derive-internal 0.10.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "anchor-derive-space" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef415ff156dc82e9ecb943189b0cb241b3a6bfc26a180234dc21bd3ef3ce0cb" -dependencies = [ + "anchor-syn", + "borsh-derive-internal", "proc-macro2", "quote", "syn 1.0.109", @@ -298,47 +176,21 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "anchor-lang" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6620c9486d9d36a4389cab5e37dc34a42ed0bfaa62e6a75a2999ce98f8f2e373" -dependencies = [ - "anchor-attribute-access-control 0.30.1", - "anchor-attribute-account 0.30.1", - "anchor-attribute-constant 0.30.1", - "anchor-attribute-error 0.30.1", - "anchor-attribute-event 0.30.1", - "anchor-attribute-program 0.30.1", - "anchor-derive-accounts 0.30.1", - "anchor-derive-serde 0.30.1", - "anchor-derive-space 0.30.1", - "anchor-lang-idl", - "arrayref", - "base64 0.21.7", - "bincode", - "borsh 0.10.4", - "bytemuck", - "getrandom 0.2.17", - "solana-program", - "thiserror 1.0.69", -] - [[package]] name = "anchor-lang" version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67d85d5376578f12d840c29ff323190f6eecd65b00a0b5f2b2f232751d049cc" dependencies = [ - "anchor-attribute-access-control 0.32.1", - "anchor-attribute-account 0.32.1", - "anchor-attribute-constant 0.32.1", - "anchor-attribute-error 0.32.1", - "anchor-attribute-event 0.32.1", - "anchor-attribute-program 0.32.1", - "anchor-derive-accounts 0.32.1", - "anchor-derive-serde 0.32.1", - "anchor-derive-space 0.32.1", + "anchor-attribute-access-control", + "anchor-attribute-account", + "anchor-attribute-constant", + "anchor-attribute-error", + "anchor-attribute-event", + "anchor-attribute-program", + "anchor-derive-accounts", + "anchor-derive-serde", + "anchor-derive-space", "anchor-lang-idl", "base64 0.21.7", "bincode", @@ -352,7 +204,7 @@ dependencies = [ "solana-instruction", "solana-instructions-sysvar", "solana-invoke", - "solana-loader-v3-interface", + "solana-loader-v3-interface 3.0.0", "solana-msg", "solana-program-entrypoint", "solana-program-error", @@ -394,11 +246,11 @@ dependencies = [ [[package]] name = "anchor-spl" -version = "0.30.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04bd077c34449319a1e4e0bc21cea572960c9ae0d0fefda0dd7c52fcc3c647a3" +checksum = "3397ab3fc5b198bbfe55d827ff58bd69f2a8d3f9f71c3732c23c2093fec4d3ef" dependencies = [ - "anchor-lang 0.30.1", + "anchor-lang", "mpl-token-metadata", "spl-associated-token-account", "spl-pod", @@ -408,25 +260,6 @@ dependencies = [ "spl-token-metadata-interface", ] -[[package]] -name = "anchor-syn" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f99daacb53b55cfd37ce14d6c9905929721137fd4c67bbab44a19802aecb622f" -dependencies = [ - "anyhow", - "bs58 0.5.1", - "cargo_toml", - "heck", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2 0.10.9", - "syn 1.0.109", - "thiserror 1.0.69", -] - [[package]] name = "anchor-syn" version = "0.32.1" @@ -434,7 +267,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b93b69aa7d099b59378433f6d7e20e1008fc10c69e48b220270e5b3f2ec4c8be" dependencies = [ "anyhow", - "bs58 0.5.1", + "bs58", "cargo_toml", "heck", "proc-macro2", @@ -452,123 +285,6 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "ark-bn254" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" -dependencies = [ - "ark-ec", - "ark-ff", - "ark-std", -] - -[[package]] -name = "ark-ec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" -dependencies = [ - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", - "itertools", - "num-traits", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", - "derivative", - "digest 0.10.7", - "itertools", - "num-bigint", - "num-traits", - "paste", - "rustc_version", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-poly" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" -dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", - "derivative", - "hashbrown 0.13.2", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-serialize-derive", - "ark-std", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-serialize-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - [[package]] name = "arrayref" version = "0.3.9" @@ -581,23 +297,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.5.0" @@ -636,9 +335,6 @@ name = "bitflags" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -dependencies = [ - "serde_core", -] [[package]] name = "bitmaps" @@ -669,7 +365,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "block-padding", "generic-array", ] @@ -682,22 +377,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "borsh" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" -dependencies = [ - "borsh-derive 0.9.3", - "hashbrown 0.11.2", -] - [[package]] name = "borsh" version = "0.10.4" @@ -718,27 +397,14 @@ dependencies = [ "cfg_aliases", ] -[[package]] -name = "borsh-derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" -dependencies = [ - "borsh-derive-internal 0.9.3", - "borsh-schema-derive-internal 0.9.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "borsh-derive" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" dependencies = [ - "borsh-derive-internal 0.10.4", - "borsh-schema-derive-internal 0.10.4", + "borsh-derive-internal", + "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", "proc-macro2", "syn 1.0.109", @@ -757,17 +423,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "borsh-derive-internal" version = "0.10.4" @@ -779,17 +434,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "borsh-schema-derive-internal" version = "0.10.4" @@ -809,13 +453,7 @@ checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e" [[package]] name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bs58" -version = "0.5.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ @@ -887,8 +525,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] @@ -904,22 +540,14 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chrono" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" -dependencies = [ - "num-traits", -] - [[package]] name = "cipher" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array", + "crypto-common", + "inout", ] [[package]] @@ -995,42 +623,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "ctr" -version = "0.8.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ "cipher", ] -[[package]] -name = "curve25519-dalek" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "serde", - "subtle", - "zeroize", -] - [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1044,6 +649,7 @@ dependencies = [ "fiat-crypto", "rand_core 0.6.4", "rustc_version", + "serde", "subtle", "zeroize", ] @@ -1059,41 +665,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.117", -] - [[package]] name = "dashmap" version = "5.5.3" @@ -1114,17 +685,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "digest" version = "0.9.0" @@ -1145,60 +705,12 @@ dependencies = [ "subtle", ] -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek 3.2.1", - "ed25519", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "ed25519-dalek-bip32" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" -dependencies = [ - "derivation-path", - "ed25519-dalek", - "hmac 0.12.1", - "sha2 0.10.9", -] - [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -1227,8 +739,8 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" name = "fight_oracle" version = "0.1.0" dependencies = [ - "anchor-lang 0.32.1", - "solana-keccak-hasher", + "anchor-lang", + "solana-keccak-hasher 2.2.1", ] [[package]] @@ -1279,7 +791,6 @@ version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "serde", "typenum", "version_check", ] @@ -1291,10 +802,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -1310,23 +819,11 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", -] - [[package]] name = "gold_clob_market" version = "0.1.0" dependencies = [ - "anchor-lang 0.32.1", + "anchor-lang", "fight_oracle", ] @@ -1334,16 +831,7 @@ dependencies = [ name = "gold_perps_market" version = "0.1.0" dependencies = [ - "anchor-lang 0.32.1", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.8", + "anchor-lang", ] [[package]] @@ -1352,7 +840,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.12", + "ahash", ] [[package]] @@ -1387,25 +875,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - [[package]] name = "hmac" version = "0.12.1" @@ -1415,23 +884,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac 0.8.1", -] - -[[package]] -name = "humantime" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" - [[package]] name = "hyperscape-bincode" version = "1.3.3" @@ -1439,12 +891,6 @@ dependencies = [ "serde", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "im" version = "15.1.0" @@ -1471,11 +917,20 @@ dependencies = [ "hashbrown 0.16.1", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "itertools" -version = "0.10.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -1486,16 +941,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - [[package]] name = "js-sys" version = "0.3.91" @@ -1536,14 +981,12 @@ dependencies = [ "arrayref", "base64 0.12.3", "digest 0.9.0", - "hmac-drbg", "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", "rand 0.7.3", "serde", "sha2 0.9.9", - "typenum", ] [[package]] @@ -1575,18 +1018,6 @@ dependencies = [ "libsecp256k1-core", ] -[[package]] -name = "light-poseidon" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" -dependencies = [ - "ark-bn254", - "ark-ff", - "num-bigint", - "thiserror 1.0.69", -] - [[package]] name = "lock_api" version = "0.4.14" @@ -1606,7 +1037,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" name = "lvr_amm" version = "0.1.0" dependencies = [ - "anchor-lang 0.30.1", + "anchor-lang", "anchor-spl", "bytemuck", "ethnum", @@ -1650,9 +1081,9 @@ dependencies = [ [[package]] name = "mpl-token-metadata" -version = "4.1.2" +version = "5.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf0f61b553e424a6234af1268456972ee66c2222e1da89079242251fa7479e5" +checksum = "046f0779684ec348e2759661361c8798d79021707b1392cb49f3b5eb911340ff" dependencies = [ "borsh 0.10.4", "num-derive 0.3.3", @@ -1768,21 +1199,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pbkdf2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" -dependencies = [ - "crypto-mac", -] - [[package]] name = "pbkdf2" version = "0.11.0" @@ -1800,9 +1216,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "polyval" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", @@ -1855,17 +1271,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "qualifier_attr" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "quote" version = "1.0.45" @@ -1875,12 +1280,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "rand" version = "0.7.3" @@ -2019,12 +1418,6 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc_version" version = "0.4.1" @@ -2114,16 +1507,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" -dependencies = [ - "serde", - "serde_with_macros", -] - [[package]] name = "serde_with" version = "3.17.0" @@ -2133,18 +1516,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_with_macros" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "sha2" version = "0.9.9" @@ -2169,18 +1540,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - [[package]] name = "sha3" version = "0.10.8" @@ -2197,18 +1556,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - [[package]] name = "sized-chunks" version = "0.6.5" @@ -2225,15 +1572,47 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "solana-account" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f949fe4edaeaea78c844023bfc1c898e0b1f5a100f8a8d2d0f85d0a7b090258" +dependencies = [ + "solana-account-info", + "solana-clock", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", +] + [[package]] name = "solana-account-info" version = "2.3.0" dependencies = [ + "hyperscape-bincode", + "serde", "solana-program-error", "solana-program-memory", "solana-pubkey", ] +[[package]] +name = "solana-address-lookup-table-interface" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1673f67efe870b64a65cb39e6194be5b26527691ce5922909939961a6e6b395" +dependencies = [ + "bincode", + "bytemuck", + "serde", + "serde_derive", + "solana-clock", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-slot-hashes", +] + [[package]] name = "solana-atomic-u64" version = "2.2.1" @@ -2244,15 +1623,59 @@ dependencies = [ ] [[package]] -name = "solana-clock" -version = "2.2.3" +name = "solana-big-mod-exp" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8584296123df8fe229b95e2ebfd37ae637fe9db9b7d4dd677ac5a78e80dbfce" +checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" +dependencies = [ + "num-bigint", + "num-traits", + "solana-define-syscall", +] + +[[package]] +name = "solana-bincode" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a3787b8cf9c9fe3dd360800e8b70982b9e5a8af9e11c354b6665dd4a003adc" +dependencies = [ + "bincode", + "serde", + "solana-instruction", +] + +[[package]] +name = "solana-blake3-hasher" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" +dependencies = [ + "blake3", + "solana-define-syscall", + "solana-hash", + "solana-sanitize", +] + +[[package]] +name = "solana-borsh" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718333bcd0a1a7aed6655aa66bef8d7fb047944922b2d3a18f49cbc13e73d004" +dependencies = [ + "borsh 0.10.4", + "borsh 1.6.0", +] + +[[package]] +name = "solana-clock" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8584296123df8fe229b95e2ebfd37ae637fe9db9b7d4dd677ac5a78e80dbfce" dependencies = [ "serde", "serde_derive", "solana-sdk-ids", - "solana-sdk-macro 2.2.1", + "solana-sdk-macro", "solana-sysvar-id", ] @@ -2270,6 +1693,20 @@ dependencies = [ "solana-stable-layout", ] +[[package]] +name = "solana-curve25519" +version = "2.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae4261b9a8613d10e77ac831a8fa60b6fa52b9b103df46d641deff9f9812a23" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek", + "solana-define-syscall", + "subtle", + "thiserror 2.0.18", +] + [[package]] name = "solana-decode-error" version = "2.3.0" @@ -2285,6 +1722,17 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ae3e2abcf541c8122eafe9a625d4d194b4023c20adde1e251f94e056bb1aee2" +[[package]] +name = "solana-derivation-path" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "939756d798b25c5ec3cca10e06212bdca3b1443cb9bb740a38124f58b258737b" +dependencies = [ + "derivation-path", + "qstring", + "uriparse", +] + [[package]] name = "solana-epoch-rewards" version = "2.2.1" @@ -2295,7 +1743,7 @@ dependencies = [ "serde_derive", "solana-hash", "solana-sdk-ids", - "solana-sdk-macro 2.2.1", + "solana-sdk-macro", "solana-sysvar-id", ] @@ -2308,52 +1756,57 @@ dependencies = [ "serde", "serde_derive", "solana-sdk-ids", - "solana-sdk-macro 2.2.1", + "solana-sdk-macro", "solana-sysvar-id", ] [[package]] -name = "solana-feature-gate-interface" -version = "2.2.2" +name = "solana-example-mocks" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84461d56cbb8bb8d539347151e0525b53910102e4bced875d49d5139708e39d3" dependencies = [ + "serde", + "serde_derive", + "solana-address-lookup-table-interface", + "solana-clock", + "solana-hash", + "solana-instruction", + "solana-keccak-hasher 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-message", + "solana-nonce", "solana-pubkey", "solana-sdk-ids", + "solana-system-interface", + "thiserror 2.0.18", ] [[package]] -name = "solana-fee-calculator" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89bc408da0fb3812bc3008189d148b4d3e08252c79ad810b245482a3f70cd8d" +name = "solana-feature-gate-interface" +version = "2.2.2" dependencies = [ - "log", + "hyperscape-bincode", "serde", "serde_derive", + "solana-account", + "solana-account-info", + "solana-instruction", + "solana-program-error", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-system-interface", ] [[package]] -name = "solana-frozen-abi" -version = "1.18.26" +name = "solana-fee-calculator" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ab2c30c15311b511c0d1151e4ab6bc9a3e080a37e7c6e7c2d96f5784cf9434" +checksum = "d89bc408da0fb3812bc3008189d148b4d3e08252c79ad810b245482a3f70cd8d" dependencies = [ - "block-buffer 0.10.4", - "bs58 0.4.0", - "bv", - "either", - "generic-array", - "im", - "lazy_static", "log", - "memmap2", - "rustc_version", "serde", - "serde_bytes", "serde_derive", - "sha2 0.10.9", - "solana-frozen-abi-macro 1.18.26", - "subtle", - "thiserror 1.0.69", ] [[package]] @@ -2363,7 +1816,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ac93e831736e9cbd1571c5c692fa7533a304f184f77cba52e5b83c4c7eeebda" dependencies = [ "boxcar", - "bs58 0.5.1", + "bs58", "bv", "bytes", "dashmap", @@ -2372,24 +1825,12 @@ dependencies = [ "memmap2", "serde", "serde_derive", - "serde_with 3.17.0", + "serde_with", "sha2 0.10.9", - "solana-frozen-abi-macro 2.2.1", + "solana-frozen-abi-macro", "thiserror 2.0.18", ] -[[package]] -name = "solana-frozen-abi-macro" -version = "1.18.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c142f779c3633ac83c84d04ff06c70e1f558c876f13358bed77ba629c7417932" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.117", -] - [[package]] name = "solana-frozen-abi-macro" version = "2.2.1" @@ -2407,6 +1848,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b96e9f0300fa287b545613f007dfe20043d7812bee255f418c1eb649c93b63" dependencies = [ + "borsh 1.6.0", "bytemuck", "bytemuck_derive", "five8", @@ -2422,6 +1864,7 @@ dependencies = [ name = "solana-instruction" version = "2.3.3" dependencies = [ + "borsh 1.6.0", "getrandom 0.2.17", "hyperscape-bincode", "js-sys", @@ -2471,10 +1914,22 @@ dependencies = [ "borsh 1.6.0", "serde", "serde_derive", - "sha3 0.10.8", + "sha3", + "solana-define-syscall", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-hash", + "solana-sanitize", +] + +[[package]] +name = "solana-keccak-hasher" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" +dependencies = [ + "sha3", "solana-define-syscall", - "solana-frozen-abi 2.3.0", - "solana-frozen-abi-macro 2.2.1", "solana-hash", "solana-sanitize", ] @@ -2488,10 +1943,24 @@ dependencies = [ "serde", "serde_derive", "solana-sdk-ids", - "solana-sdk-macro 2.2.1", + "solana-sdk-macro", "solana-sysvar-id", ] +[[package]] +name = "solana-loader-v2-interface" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ab08006dad78ae7cd30df8eea0539e207d08d91eaefb3e1d49a446e1c49654" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", +] + [[package]] name = "solana-loader-v3-interface" version = "3.0.0" @@ -2508,14 +1977,56 @@ dependencies = [ ] [[package]] -name = "solana-logger" -version = "1.18.26" +name = "solana-loader-v3-interface" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f7162a05b8b0773156b443bccd674ea78bb9aa406325b467ea78c06c99a63a2" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-system-interface", +] + +[[package]] +name = "solana-loader-v4-interface" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121d36ffb3c6b958763312cbc697fbccba46ee837d3a0aa4fc0e90fcb3b884f3" +checksum = "706a777242f1f39a83e2a96a2a6cb034cb41169c6ecbee2cf09cb873d9659e7e" dependencies = [ - "env_logger", + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-system-interface", +] + +[[package]] +name = "solana-message" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1796aabce376ff74bf89b78d268fa5e683d7d7a96a0a4e4813ec34de49d5314b" +dependencies = [ + "bincode", + "blake3", "lazy_static", - "log", + "serde", + "serde_derive", + "solana-bincode", + "solana-hash", + "solana-instruction", + "solana-pubkey", + "solana-sanitize", + "solana-sdk-ids", + "solana-short-vec", + "solana-system-interface", + "solana-transaction-error", + "wasm-bindgen", ] [[package]] @@ -2527,59 +2038,104 @@ dependencies = [ "solana-define-syscall", ] +[[package]] +name = "solana-native-token" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61515b880c36974053dd499c0510066783f0cc6ac17def0c7ef2a244874cf4a9" + +[[package]] +name = "solana-nonce" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703e22eb185537e06204a5bd9d509b948f0066f2d1d814a6f475dafb3ddf1325" +dependencies = [ + "serde", + "serde_derive", + "solana-fee-calculator", + "solana-hash", + "solana-pubkey", + "solana-sha256-hasher", +] + [[package]] name = "solana-program" -version = "1.18.26" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c10f4588cefd716b24a1a40dd32c278e43a560ab8ce4de6b5805c9d113afdfa1" +checksum = "98eca145bd3545e2fbb07166e895370576e47a00a7d824e325390d33bf467210" dependencies = [ - "ark-bn254", - "ark-ec", - "ark-ff", - "ark-serialize", - "base64 0.21.7", "bincode", - "bitflags", "blake3", "borsh 0.10.4", - "borsh 0.9.3", "borsh 1.6.0", - "bs58 0.4.0", - "bv", + "bs58", "bytemuck", - "cc", "console_error_panic_hook", "console_log", - "curve25519-dalek 3.2.1", "getrandom 0.2.17", - "itertools", - "js-sys", "lazy_static", - "libc", - "libsecp256k1", - "light-poseidon", "log", "memoffset", "num-bigint", "num-derive 0.4.2", "num-traits", - "parking_lot", "rand 0.8.5", - "rustc_version", - "rustversion", "serde", "serde_bytes", "serde_derive", - "serde_json", - "sha2 0.10.9", - "sha3 0.10.8", - "solana-frozen-abi 1.18.26", - "solana-frozen-abi-macro 1.18.26", - "solana-sdk-macro 1.18.26", - "thiserror 1.0.69", - "tiny-bip39", + "solana-account-info", + "solana-address-lookup-table-interface", + "solana-atomic-u64", + "solana-big-mod-exp", + "solana-bincode", + "solana-blake3-hasher", + "solana-borsh", + "solana-clock", + "solana-cpi", + "solana-decode-error", + "solana-define-syscall", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-example-mocks", + "solana-feature-gate-interface", + "solana-fee-calculator", + "solana-hash", + "solana-instruction", + "solana-instructions-sysvar", + "solana-keccak-hasher 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-last-restart-slot", + "solana-loader-v2-interface", + "solana-loader-v3-interface 5.0.0", + "solana-loader-v4-interface", + "solana-message", + "solana-msg", + "solana-native-token", + "solana-nonce", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey", + "solana-rent", + "solana-sanitize", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-secp256k1-recover", + "solana-serde-varint", + "solana-serialize-utils", + "solana-sha256-hasher", + "solana-short-vec", + "solana-slot-hashes", + "solana-slot-history", + "solana-stable-layout", + "solana-stake-interface", + "solana-system-interface", + "solana-sysvar", + "solana-sysvar-id", + "solana-vote-interface", + "thiserror 2.0.18", "wasm-bindgen", - "zeroize", ] [[package]] @@ -2602,6 +2158,8 @@ checksum = "9ee2e0217d642e2ea4bee237f37bd61bb02aec60da3647c48ff88f6556ade775" dependencies = [ "borsh 1.6.0", "num-traits", + "serde", + "serde_derive", "solana-decode-error", "solana-instruction", "solana-msg", @@ -2642,7 +2200,7 @@ dependencies = [ "borsh 1.6.0", "bytemuck", "bytemuck_derive", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "five8", "five8_const", "getrandom 0.2.17", @@ -2667,7 +2225,7 @@ dependencies = [ "serde", "serde_derive", "solana-sdk-ids", - "solana-sdk-macro 2.2.1", + "solana-sdk-macro", "solana-sysvar-id", ] @@ -2677,61 +2235,6 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61f1bc1357b8188d9c4a3af3fc55276e56987265eb7ad073ae6f8180ee54cecf" -[[package]] -name = "solana-sdk" -version = "1.18.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "580ad66c2f7a4c3cb3244fe21440546bd500f5ecb955ad9826e92a78dded8009" -dependencies = [ - "assert_matches", - "base64 0.21.7", - "bincode", - "bitflags", - "borsh 1.6.0", - "bs58 0.4.0", - "bytemuck", - "byteorder", - "chrono", - "derivation-path", - "digest 0.10.7", - "ed25519-dalek", - "ed25519-dalek-bip32", - "generic-array", - "hmac 0.12.1", - "itertools", - "js-sys", - "lazy_static", - "libsecp256k1", - "log", - "memmap2", - "num-derive 0.4.2", - "num-traits", - "num_enum", - "pbkdf2 0.11.0", - "qstring", - "qualifier_attr", - "rand 0.7.3", - "rand 0.8.5", - "rustc_version", - "rustversion", - "serde", - "serde_bytes", - "serde_derive", - "serde_json", - "serde_with 2.3.3", - "sha2 0.10.9", - "sha3 0.10.8", - "siphasher", - "solana-frozen-abi 1.18.26", - "solana-frozen-abi-macro 1.18.26", - "solana-logger", - "solana-program", - "solana-sdk-macro 1.18.26", - "thiserror 1.0.69", - "uriparse", - "wasm-bindgen", -] - [[package]] name = "solana-sdk-ids" version = "2.2.1" @@ -2743,27 +2246,25 @@ dependencies = [ [[package]] name = "solana-sdk-macro" -version = "1.18.26" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b75d0f193a27719257af19144fdaebec0415d1c9e9226ae4bd29b791be5e9bd" +checksum = "86280da8b99d03560f6ab5aca9de2e38805681df34e0bb8f238e69b29433b9df" dependencies = [ - "bs58 0.4.0", + "bs58", "proc-macro2", "quote", - "rustversion", "syn 2.0.117", ] [[package]] -name = "solana-sdk-macro" +name = "solana-secp256k1-recover" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86280da8b99d03560f6ab5aca9de2e38805681df34e0bb8f238e69b29433b9df" +checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" dependencies = [ - "bs58 0.5.1", - "proc-macro2", - "quote", - "syn 2.0.117", + "libsecp256k1", + "solana-define-syscall", + "thiserror 2.0.18", ] [[package]] @@ -2775,6 +2276,35 @@ dependencies = [ "hashbrown 0.15.2", ] +[[package]] +name = "solana-seed-derivable" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beb82b5adb266c6ea90e5cf3967235644848eac476c5a1f2f9283a143b7c97f" +dependencies = [ + "solana-derivation-path", +] + +[[package]] +name = "solana-seed-phrase" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36187af2324f079f65a675ec22b31c24919cb4ac22c79472e85d819db9bbbc15" +dependencies = [ + "hmac", + "pbkdf2", + "sha2 0.10.9", +] + +[[package]] +name = "solana-serde-varint" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7e155eba458ecfb0107b98236088c3764a09ddf0201ec29e52a0be40857113" +dependencies = [ + "serde", +] + [[package]] name = "solana-serialize-utils" version = "2.2.1" @@ -2797,6 +2327,36 @@ dependencies = [ "solana-hash", ] +[[package]] +name = "solana-short-vec" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c54c66f19b9766a56fa0057d060de8378676cb64987533fa088861858fc5a69" +dependencies = [ + "serde", +] + +[[package]] +name = "solana-signature" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c8ec8e657aecfc187522fc67495142c12f35e55ddeca8698edbb738b8dbd8c" +dependencies = [ + "five8", + "solana-sanitize", +] + +[[package]] +name = "solana-signer" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c41991508a4b02f021c1342ba00bcfa098630b213726ceadc7cb032e051975b" +dependencies = [ + "solana-pubkey", + "solana-signature", + "solana-transaction-error", +] + [[package]] name = "solana-slot-hashes" version = "2.2.1" @@ -2839,6 +2399,8 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c" dependencies = [ + "borsh 0.10.4", + "borsh 1.6.0", "num-traits", "serde", "serde_derive", @@ -2873,6 +2435,8 @@ name = "solana-sysvar" version = "2.3.0" dependencies = [ "base64 0.22.1", + "bytemuck", + "bytemuck_derive", "hyperscape-bincode", "lazy_static", "serde", @@ -2894,7 +2458,7 @@ dependencies = [ "solana-rent", "solana-sanitize", "solana-sdk-ids", - "solana-sdk-macro 2.2.1", + "solana-sdk-macro", "solana-slot-hashes", "solana-slot-history", "solana-stake-interface", @@ -2912,58 +2476,110 @@ dependencies = [ ] [[package]] -name = "solana-zk-token-sdk" -version = "1.18.26" +name = "solana-transaction-error" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a9dc8fdb61c6088baab34fc3a8b8473a03a7a5fd404ed8dd502fa79b67cb1" +dependencies = [ + "solana-instruction", + "solana-sanitize", +] + +[[package]] +name = "solana-vote-interface" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b80d57478d6599d30acc31cc5ae7f93ec2361a06aefe8ea79bc81739a08af4c3" +dependencies = [ + "bincode", + "num-derive 0.4.2", + "num-traits", + "serde", + "serde_derive", + "solana-clock", + "solana-decode-error", + "solana-hash", + "solana-instruction", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-serde-varint", + "solana-serialize-utils", + "solana-short-vec", + "solana-system-interface", +] + +[[package]] +name = "solana-zk-sdk" +version = "2.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cbdf4249b6dfcbba7d84e2b53313698043f60f8e22ce48286e6fbe8a17c8d16" +checksum = "97b9fc6ec37d16d0dccff708ed1dd6ea9ba61796700c3bb7c3b401973f10f63b" dependencies = [ "aes-gcm-siv", - "base64 0.21.7", + "base64 0.22.1", "bincode", "bytemuck", - "byteorder", - "curve25519-dalek 3.2.1", - "getrandom 0.1.16", + "bytemuck_derive", + "curve25519-dalek", "itertools", - "lazy_static", + "js-sys", "merlin", "num-derive 0.4.2", "num-traits", - "rand 0.7.3", + "rand 0.8.5", "serde", + "serde_derive", "serde_json", - "sha3 0.9.1", - "solana-program", - "solana-sdk", + "sha3", + "solana-derivation-path", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", "subtle", - "thiserror 1.0.69", + "thiserror 2.0.18", + "wasm-bindgen", "zeroize", ] [[package]] name = "spl-associated-token-account" -version = "3.0.4" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143109d789171379e6143ef23191786dfaac54289ad6e7917cfb26b36c432b10" +checksum = "ae179d4a26b3c7a20c839898e6aed84cb4477adf108a366c95532f058aea041b" dependencies = [ - "assert_matches", "borsh 1.6.0", "num-derive 0.4.2", "num-traits", "solana-program", + "spl-associated-token-account-client", "spl-token", "spl-token-2022", - "thiserror 1.0.69", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-associated-token-account-client" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f8349dbcbe575f354f9a533a21f272f3eb3808a49e2fdc1c34393b88ba76cb" +dependencies = [ + "solana-instruction", + "solana-pubkey", ] [[package]] name = "spl-discriminator" -version = "0.2.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210101376962bb22bb13be6daea34656ea1cbc248fce2164b146e39203b55e03" +checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ "bytemuck", - "solana-program", + "solana-program-error", + "solana-sha256-hasher", "spl-discriminator-derive", ] @@ -2991,46 +2607,83 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "spl-elgamal-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65edfeed09cd4231e595616aa96022214f9c9d2be02dea62c2b30d5695a6833a" +dependencies = [ + "bytemuck", + "solana-account-info", + "solana-cpi", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-system-interface", + "solana-sysvar", + "solana-zk-sdk", + "spl-pod", + "spl-token-confidential-transfer-proof-extraction", +] + [[package]] name = "spl-memo" -version = "4.0.4" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49f49f95f2d02111ded31696ab38a081fab623d4c76bd4cb074286db4560836" +checksum = "9f09647c0974e33366efeb83b8e2daebb329f0420149e74d3a4bd2c08cf9f7cb" dependencies = [ - "solana-program", + "solana-account-info", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", ] [[package]] name = "spl-pod" -version = "0.2.5" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52d84c55efeef8edcc226743dc089d7e3888b8e3474569aa3eff152b37b9996" +checksum = "d994afaf86b779104b4a95ba9ca75b8ced3fdb17ee934e38cb69e72afbe17799" dependencies = [ "borsh 1.6.0", "bytemuck", - "solana-program", - "solana-zk-token-sdk", - "spl-program-error", + "bytemuck_derive", + "num-derive 0.4.2", + "num-traits", + "solana-decode-error", + "solana-msg", + "solana-program-error", + "solana-program-option", + "solana-pubkey", + "solana-zk-sdk", + "thiserror 2.0.18", ] [[package]] name = "spl-program-error" -version = "0.4.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45a49acb925db68aa501b926096b2164adbdcade7a0c24152af9f0742d0a602" +checksum = "9cdebc8b42553070b75aa5106f071fef2eb798c64a7ec63375da4b1f058688c6" dependencies = [ "num-derive 0.4.2", "num-traits", - "solana-program", + "solana-decode-error", + "solana-msg", + "solana-program-error", "spl-program-error-derive", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] name = "spl-program-error-derive" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +checksum = "2a2539e259c66910d78593475540e8072f0b10f0f61d7607bbf7593899ed52d0" dependencies = [ "proc-macro2", "quote", @@ -3040,124 +2693,229 @@ dependencies = [ [[package]] name = "spl-tlv-account-resolution" -version = "0.6.5" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fab8edfd37be5fa17c9e42c1bff86abbbaf0494b031b37957f2728ad2ff842ba" +checksum = "1408e961215688715d5a1063cbdcf982de225c45f99c82b4f7d7e1dd22b998d7" dependencies = [ "bytemuck", - "solana-program", + "num-derive 0.4.2", + "num-traits", + "solana-account-info", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", "spl-discriminator", "spl-pod", "spl-program-error", "spl-type-length-value", + "thiserror 2.0.18", ] [[package]] name = "spl-token" -version = "4.0.3" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9eb465e4bf5ce1d498f05204c8089378c1ba34ef2777ea95852fc53a1fd4fb2" +checksum = "053067c6a82c705004f91dae058b11b4780407e9ccd6799dc9e7d0fab5f242da" dependencies = [ "arrayref", "bytemuck", "num-derive 0.4.2", "num-traits", "num_enum", - "solana-program", - "thiserror 1.0.69", + "solana-account-info", + "solana-cpi", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-sysvar", + "thiserror 2.0.18", ] [[package]] name = "spl-token-2022" -version = "3.0.5" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c39e416aeb1ea0b22f3b2bbecaf7e38a92a1aa8f4a0c5785c94179694e846a0" +checksum = "31f0dfbb079eebaee55e793e92ca5f433744f4b71ee04880bfd6beefba5973e5" dependencies = [ "arrayref", "bytemuck", "num-derive 0.4.2", "num-traits", "num_enum", - "solana-program", + "solana-account-info", + "solana-clock", + "solana-cpi", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-native-token", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", "solana-security-txt", - "solana-zk-token-sdk", + "solana-system-interface", + "solana-sysvar", + "solana-zk-sdk", + "spl-elgamal-registry", "spl-memo", "spl-pod", "spl-token", + "spl-token-confidential-transfer-ciphertext-arithmetic", + "spl-token-confidential-transfer-proof-extraction", + "spl-token-confidential-transfer-proof-generation", "spl-token-group-interface", "spl-token-metadata-interface", "spl-transfer-hook-interface", "spl-type-length-value", - "thiserror 1.0.69", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-ciphertext-arithmetic" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cddd52bfc0f1c677b41493dafa3f2dbbb4b47cf0990f08905429e19dc8289b35" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "solana-curve25519", + "solana-zk-sdk", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe2629860ff04c17bafa9ba4bed8850a404ecac81074113e1f840dbd0ebb7bd6" +dependencies = [ + "bytemuck", + "solana-account-info", + "solana-curve25519", + "solana-instruction", + "solana-instructions-sysvar", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "solana-sdk-ids", + "solana-zk-sdk", + "spl-pod", + "thiserror 2.0.18", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa27b9174bea869a7ebf31e0be6890bce90b1a4288bc2bbf24bd413f80ae3fde" +dependencies = [ + "curve25519-dalek", + "solana-zk-sdk", + "thiserror 2.0.18", ] [[package]] name = "spl-token-group-interface" -version = "0.2.5" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "014817d6324b1e20c4bbc883e8ee30a5faa13e59d91d1b2b95df98b920150c17" +checksum = "5597b4cd76f85ce7cd206045b7dc22da8c25516573d42d267c8d1fd128db5129" dependencies = [ "bytemuck", - "solana-program", + "num-derive 0.4.2", + "num-traits", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", "spl-discriminator", "spl-pod", - "spl-program-error", + "thiserror 2.0.18", ] [[package]] name = "spl-token-metadata-interface" -version = "0.3.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3da00495b602ebcf5d8ba8b3ecff1ee454ce4c125c9077747be49c2d62335ba" +checksum = "304d6e06f0de0c13a621464b1fd5d4b1bebf60d15ca71a44d3839958e0da16ee" dependencies = [ "borsh 1.6.0", - "solana-program", + "num-derive 0.4.2", + "num-traits", + "solana-borsh", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", "spl-discriminator", "spl-pod", - "spl-program-error", "spl-type-length-value", + "thiserror 2.0.18", ] [[package]] name = "spl-transfer-hook-interface" -version = "0.6.5" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b5c08a89838e5a2931f79b17f611857f281a14a2100968a3ccef352cb7414b" +checksum = "a7e905b849b6aba63bde8c4badac944ebb6c8e6e14817029cbe1bc16829133bd" dependencies = [ "arrayref", "bytemuck", - "solana-program", + "num-derive 0.4.2", + "num-traits", + "solana-account-info", + "solana-cpi", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", "spl-discriminator", "spl-pod", "spl-program-error", "spl-tlv-account-resolution", "spl-type-length-value", + "thiserror 2.0.18", ] [[package]] name = "spl-type-length-value" -version = "0.4.6" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c872f93d0600e743116501eba2d53460e73a12c9a496875a42a7d70e034fe06d" +checksum = "d417eb548214fa822d93f84444024b4e57c13ed6719d4dcc68eec24fb481e9f5" dependencies = [ "bytemuck", - "solana-program", + "num-derive 0.4.2", + "num-traits", + "solana-account-info", + "solana-decode-error", + "solana-msg", + "solana-program-error", "spl-discriminator", "spl-pod", - "spl-program-error", + "thiserror 2.0.18", ] -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - [[package]] name = "subtle" -version = "2.4.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -3181,15 +2939,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -3230,25 +2979,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "tiny-bip39" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" -dependencies = [ - "anyhow", - "hmac 0.8.1", - "once_cell", - "pbkdf2 0.4.0", - "rand 0.7.3", - "rustc-hash", - "sha2 0.9.9", - "thiserror 1.0.69", - "unicode-normalization", - "wasm-bindgen", - "zeroize", -] - [[package]] name = "tinyvec" version = "1.10.0" @@ -3356,15 +3086,6 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unicode-normalization" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -3373,11 +3094,11 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "universal-hash" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "generic-array", + "crypto-common", "subtle", ] @@ -3409,15 +3130,6 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" version = "0.2.114" @@ -3473,52 +3185,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - [[package]] name = "winnow" version = "0.7.15" @@ -3528,12 +3200,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" - [[package]] name = "zerocopy" version = "0.8.40" @@ -3556,9 +3222,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.3.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/Cargo.toml b/packages/hyperbet-solana/anchor/programs/lvr_amm/Cargo.toml index 2725dc2e..9e8ac32f 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/Cargo.toml +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/Cargo.toml @@ -20,8 +20,8 @@ custom-heap = [] custom-panic = [] [dependencies] -anchor-lang = {version = "0.30.1", features = ["init-if-needed"]} -anchor-spl = {version = "0.30.1", features = ["metadata"]} +anchor-lang = {version = "0.32.1", features = ["init-if-needed"]} +anchor-spl = {version = "0.32.1", features = ["metadata"]} bytemuck = { version = "1.20.0", features = ["min_const_generics"] } ethnum = "1.5.0" diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/error.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/error.rs index d3803343..39dc92b6 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/error.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/error.rs @@ -73,4 +73,19 @@ pub enum PredictionMarketError { #[msg("Config is frozen")] ConfigFrozen, + + #[msg("Invalid duel state account")] + InvalidDuelState, + + #[msg("AMM config account required for oracle settlement")] + MissingAmmConfig, + + #[msg("Fight oracle program mismatch")] + InvalidFightOracleProgram, + + #[msg("AMM Newton-Raphson solver did not converge")] + MathConvergenceError, + + #[msg("AMM fixed-point overflow")] + MathFixedPointOverflow, } diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/buy.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/buy.rs index 9b467d97..587ec2a0 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/buy.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/buy.rs @@ -25,6 +25,7 @@ pub fn buy_instruction(ctx: Context, bet_id: u64, outcome: u8, amount_in: u bet.side_won.is_none(), PredictionMarketError::BetAlreadySettled ); + require!(bet.is_initialized, PredictionMarketError::BetNotInitialized); let is_buy_yes = outcome == 0; @@ -49,12 +50,12 @@ pub fn buy_instruction(ctx: Context, bet_id: u64, outcome: u8, amount_in: u .ok_or(PredictionMarketError::MathOverflow)?; let amount_out = math::get_swap_amount( - !is_buy_yes, - bet.reserves[0], - bet.reserves[1], - liq, + !is_buy_yes, + bet.reserves[0], + bet.reserves[1], + liq, net_amount_in - ); + )?; // Update Virtual Reserves // EVM: diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/create_bet.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/create_bet.rs index 6ef9cdad..a969050e 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/create_bet.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/create_bet.rs @@ -30,6 +30,7 @@ pub fn create_bet( bet.is_dynamic = is_dynamic; bet.initial_liq = math::calc_initial_liquidity(initial_liq); bet.reserves = [initial_liq, initial_liq]; + bet.duel_key = duel_key; bet.bet_prompt = bet_prompt; bet.created_at = clock.unix_timestamp; @@ -41,7 +42,6 @@ pub fn create_bet( // Read fee/treasury from protocol config — not caller inputs bet.treasury = config.treasury; bet.fee_bps = config.fee_bps; - bet.duel_key = duel_key; Ok(()) } diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/get_price.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/get_price.rs index 97789be5..2df5d13d 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/get_price.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/get_price.rs @@ -16,7 +16,7 @@ pub fn get_price_instruction(ctx: Context, outcome: u8) -> Result bet.initial_liq }; - let price_yes = math::calc_price(bet.reserves[0], bet.reserves[1], liq); + let price_yes = math::calc_price(bet.reserves[0], bet.reserves[1], liq)?; if outcome == 0 { Ok(price_yes) diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/init_config.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/init_config.rs index 283cea35..3abaad63 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/init_config.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/init_config.rs @@ -6,16 +6,19 @@ pub fn initialize_amm_config( ctx: Context, treasury: Pubkey, market_maker: Pubkey, + fight_oracle_program: Pubkey, fee_bps: u16, ) -> Result<()> { require!(treasury != Pubkey::default(), PredictionMarketError::InvalidAddress); require!(market_maker != Pubkey::default(), PredictionMarketError::InvalidAddress); + require!(fight_oracle_program != Pubkey::default(), PredictionMarketError::InvalidAddress); require!(fee_bps <= 1000, PredictionMarketError::FeeTooHigh); let config = &mut ctx.accounts.amm_config; config.authority = ctx.accounts.signer.key(); config.treasury = treasury; config.market_maker = market_maker; + config.fight_oracle_program = fight_oracle_program; config.fee_bps = fee_bps; config.config_frozen = false; config.paused = false; @@ -24,6 +27,7 @@ pub fn initialize_amm_config( emit!(AmmConfigInitialized { authority: config.authority, treasury: config.treasury, + fight_oracle_program: config.fight_oracle_program, fee_bps: config.fee_bps, }); @@ -106,6 +110,7 @@ pub struct SetAmmPaused<'info> { pub struct AmmConfigInitialized { pub authority: Pubkey, pub treasury: Pubkey, + pub fight_oracle_program: Pubkey, pub fee_bps: u16, } diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/sell.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/sell.rs index a63153b1..db0b2bd8 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/sell.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/sell.rs @@ -47,12 +47,12 @@ pub fn sell_instruction(ctx: Context, bet_id: u64, outcome: u8, amount_in: .ok_or(PredictionMarketError::MathOverflow)?; let amount_out = math::get_swap_amount( - is_sell_yes, - bet.reserves[0], - bet.reserves[1], - liq, + is_sell_yes, + bet.reserves[0], + bet.reserves[1], + liq, net_amount_in - ); + )?; // Update Virtual Reserves if is_sell_yes { diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/settle_bet.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/settle_bet.rs index 9093fc6f..ba819a98 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/settle_bet.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/instructions/settle_bet.rs @@ -1,9 +1,8 @@ use anchor_lang::prelude::*; -use core::str::FromStr; use crate::{ error::PredictionMarketError, - state::{admin::Admin, bet::Bet}, + state::{admin::Admin, bet::Bet, config::AmmConfig}, }; const DUEL_STATE_DISCRIMINATOR: [u8; 8] = [0x95, 0xd5, 0x3b, 0xa5, 0x7c, 0x74, 0x91, 0x78]; @@ -71,12 +70,12 @@ pub fn settle_bet_instruction(ctx: Context, _bet_id: u64, side_won: u // If an oracle duel_state is provided, read winner from oracle (trustless path) let final_side_won = if let Some(duel_account) = &ctx.accounts.duel_state { - let fight_oracle_program_id = Pubkey::from_str("B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo") - .map_err(|_| error!(PredictionMarketError::InvalidOracleAccount))?; + let amm_config = ctx.accounts.amm_config.as_ref() + .ok_or(error!(PredictionMarketError::MissingAmmConfig))?; require_keys_eq!( *duel_account.owner, - fight_oracle_program_id, - PredictionMarketError::InvalidOracleAccount + amm_config.fight_oracle_program, + PredictionMarketError::InvalidFightOracleProgram ); let data = duel_account.try_borrow_data()?; @@ -155,6 +154,13 @@ pub struct SettleBet<'info> { )] pub bet: Account<'info, Bet>, + /// Optional: AmmConfig for oracle program ID validation (required when duel_state is provided) + #[account( + seeds = [b"amm_config"], + bump = amm_config.bump, + )] + pub amm_config: Option>, + /// Optional: fight_oracle DuelState account. When provided, winner is read /// from the oracle rather than trusting the caller's `side_won` argument. /// CHECK: We manually deserialize the data at known offsets. diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/lib.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/lib.rs index b2d864de..6f4941f8 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/lib.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/lib.rs @@ -22,9 +22,10 @@ pub mod lvr_amm { ctx: Context, treasury: Pubkey, market_maker: Pubkey, + fight_oracle_program: Pubkey, fee_bps: u16, ) -> Result<()> { - initialize_amm_config(ctx, treasury, market_maker, fee_bps) + initialize_amm_config(ctx, treasury, market_maker, fight_oracle_program, fee_bps) } pub fn freeze_config(ctx: Context) -> Result<()> { diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/math.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/math.rs index f16298c0..1570f488 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/math.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/math.rs @@ -4,8 +4,11 @@ /// but public API uses u64 scaled by 1e6 (SPL convention). /// /// Replaces f64 to ensure deterministic consensus across validators. +use anchor_lang::prelude::*; use ethnum::I256; +use crate::error::PredictionMarketError; + const SCALE: u64 = 1_000_000; // SPL 6-decimal scale const FRAC_BITS: u32 = 64; @@ -31,21 +34,21 @@ fn q_to_u64(val: i128) -> u64 { } /// Q64.64 multiply: (a * b) >> 64 -fn q_mul(a: i128, b: i128) -> i128 { +fn q_mul(a: i128, b: i128) -> Result { i256_to_i128((I256::new(a) * I256::new(b)) >> FRAC_BITS) } /// Q64.64 divide: (a << 64) / b -fn q_div(a: i128, b: i128) -> i128 { - assert!(b != 0, "q_div: division by zero"); +fn q_div(a: i128, b: i128) -> Result { + require!(b != 0, PredictionMarketError::MathFixedPointOverflow); i256_to_i128((I256::new(a) << FRAC_BITS) / I256::new(b)) } -fn i256_to_i128(value: I256) -> i128 { +fn i256_to_i128(value: I256) -> Result { let min = I256::new(i128::MIN); let max = I256::new(i128::MAX); - assert!(value >= min && value <= max, "i256_to_i128: overflow"); - value.as_i128() + require!(value >= min && value <= max, PredictionMarketError::MathFixedPointOverflow); + Ok(value.as_i128()) } fn q_abs(val: i128) -> i128 { @@ -55,14 +58,14 @@ fn q_abs(val: i128) -> i128 { /// Polynomial approximation of erf(x) for |x| <= 4. /// Uses Abramowitz and Stegun approximation 7.1.28 (max error ~1.5e-7). /// For |x| > 4, erf(x) ≈ ±1. -fn q_erf(x: i128) -> i128 { +fn q_erf(x: i128) -> Result { let is_neg = x < 0; let ax = q_abs(x); // For large |x|, erf → ±1 let four_q = 4i128 << FRAC_BITS; if ax >= four_q { - return if is_neg { -Q_ONE } else { Q_ONE }; + return Ok(if is_neg { -Q_ONE } else { Q_ONE }); } // Abramowitz & Stegun constants (scaled to Q64.64) @@ -75,98 +78,98 @@ fn q_erf(x: i128) -> i128 { let a5: i128 = 19_580_373_992_048_084_992; // 1.061405429 // t = 1 / (1 + p*|x|) - let px = q_mul(p, ax); + let px = q_mul(p, ax)?; let denom = Q_ONE + px; - let t = q_div(Q_ONE, denom); + let t = q_div(Q_ONE, denom)?; // Horner's method: poly = ((((a5*t + a4)*t + a3)*t + a2)*t + a1)*t let mut poly = a5; - poly = q_mul(poly, t) + a4; - poly = q_mul(poly, t) + a3; - poly = q_mul(poly, t) + a2; - poly = q_mul(poly, t) + a1; - poly = q_mul(poly, t); + poly = q_mul(poly, t)? + a4; + poly = q_mul(poly, t)? + a3; + poly = q_mul(poly, t)? + a2; + poly = q_mul(poly, t)? + a1; + poly = q_mul(poly, t)?; // exp(-x^2): use the integer exp approximation - let x2 = q_mul(ax, ax); - let exp_neg_x2 = q_exp_neg(x2); + let x2 = q_mul(ax, ax)?; + let exp_neg_x2 = q_exp_neg(x2)?; // erf = 1 - poly * exp(-x^2) - let result = Q_ONE - q_mul(poly, exp_neg_x2); + let result = Q_ONE - q_mul(poly, exp_neg_x2)?; - if is_neg { -result } else { result } + Ok(if is_neg { -result } else { result }) } /// Approximate exp(-x) for x >= 0 using the identity exp(-x) = (1 - x/n)^n /// with piecewise linear segments for better accuracy. -fn q_exp_neg(x: i128) -> i128 { - if x <= 0 { return Q_ONE; } +fn q_exp_neg(x: i128) -> Result { + if x <= 0 { return Ok(Q_ONE); } // For very large x, exp(-x) ≈ 0 let ten_q = 10i128 << FRAC_BITS; - if x >= ten_q { return 0; } + if x >= ten_q { return Ok(0); } // Use repeated squaring: exp(-x) = exp(-x/16)^16 // This keeps the argument small for better accuracy let small_x = x >> 4; // x/16 // exp(-small_x) ≈ 1 - small_x + small_x^2/2 - small_x^3/6 (Taylor 4 terms) - let x2 = q_mul(small_x, small_x); - let x3 = q_mul(x2, small_x); + let x2 = q_mul(small_x, small_x)?; + let x3 = q_mul(x2, small_x)?; let half_x2 = x2 >> 1; // x^2 / 2 - let sixth_x3 = q_div(x3, 6i128 << FRAC_BITS); // x^3 / 6 + let sixth_x3 = q_div(x3, 6i128 << FRAC_BITS)?; // x^3 / 6 let mut result = Q_ONE - small_x + half_x2 - sixth_x3; if result < 0 { result = 0; } // Square 4 times to get exp(-x) from exp(-x/16) for _ in 0..4 { - result = q_mul(result, result); + result = q_mul(result, result)?; if result < 0 { result = 0; } } - result + Ok(result) } /// Gaussian CDF: Φ(z) = 0.5 * (1 + erf(z / sqrt(2))) -fn gaussian_cdf_q(z: i128) -> i128 { - let z_over_sqrt2 = q_div(z, Q_SQRT_2); - let erf_val = q_erf(z_over_sqrt2); +fn gaussian_cdf_q(z: i128) -> Result { + let z_over_sqrt2 = q_div(z, Q_SQRT_2)?; + let erf_val = q_erf(z_over_sqrt2)?; // 0.5 * (1 + erf) - (Q_ONE + erf_val) >> 1 + Ok((Q_ONE + erf_val) >> 1) } /// Gaussian PDF: φ(z) = exp(-z²/2) / sqrt(2π) -fn gaussian_pdf_q(z: i128) -> i128 { - let z2 = q_mul(z, z); +fn gaussian_pdf_q(z: i128) -> Result { + let z2 = q_mul(z, z)?; let half_z2 = z2 >> 1; // z²/2 - let exp_val = q_exp_neg(half_z2); + let exp_val = q_exp_neg(half_z2)?; q_div(exp_val, Q_SQRT_2PI) } /// AMM invariant: f(x, y, L) = (y-x)*Φ(z) + L*φ(z) - y, where z = (y-x)/L -fn amm_func_q(x: i128, y: i128, l: i128) -> i128 { +fn amm_func_q(x: i128, y: i128, l: i128) -> Result { let diff = y - x; - let z = q_div(diff, l); - let cdf = gaussian_cdf_q(z); - let pdf = gaussian_pdf_q(z); + let z = q_div(diff, l)?; + let cdf = gaussian_cdf_q(z)?; + let pdf = gaussian_pdf_q(z)?; - q_mul(diff, cdf) + q_mul(l, pdf) - y + Ok(q_mul(diff, cdf)? + q_mul(l, pdf)? - y) } /// Derivative of invariant w.r.t. x: f'(x) = -Φ(z) -fn func_derivative_q(x: i128, y: i128, l: i128) -> i128 { - let z = q_div(y - x, l); - let mut deriv = -gaussian_cdf_q(z); +fn func_derivative_q(x: i128, y: i128, l: i128) -> Result { + let z = q_div(y - x, l)?; + let mut deriv = -gaussian_cdf_q(z)?; if q_abs(deriv) < Q_MIN_DERIVATIVE { deriv = if deriv < 0 { -Q_MIN_DERIVATIVE } else { Q_MIN_DERIVATIVE }; } - deriv + Ok(deriv) } /// Newton-Raphson solver for the new reserve given modified counterpart reserve -fn get_new_reserve_q(x_guess: i128, y: i128, l: i128) -> i128 { +fn get_new_reserve_q(x_guess: i128, y: i128, l: i128) -> Result { let mut t = if q_abs(x_guess) < Q_MIN_RESERVE { y >> 1 // Better initial guess: y/2 } else { @@ -174,17 +177,17 @@ fn get_new_reserve_q(x_guess: i128, y: i128, l: i128) -> i128 { }; for _ in 0..MAX_NEWTON_ITERS { - let f = amm_func_q(t, y, l); + let f = amm_func_q(t, y, l)?; if q_abs(f) < Q_APPROX { let res = q_abs(t); - return if res < Q_MIN_RESERVE { Q_MIN_RESERVE } else { res }; + return Ok(if res < Q_MIN_RESERVE { Q_MIN_RESERVE } else { res }); } - let deriv = func_derivative_q(t, y, l); - assert!(deriv != 0, "get_new_reserve_q: zero derivative"); - t = t - q_div(f, deriv); + let deriv = func_derivative_q(t, y, l)?; + require!(deriv != 0, PredictionMarketError::MathConvergenceError); + t = t - q_div(f, deriv)?; } - panic!("get_new_reserve_q: Newton-Raphson did not converge after {} iterations", MAX_NEWTON_ITERS); + err!(PredictionMarketError::MathConvergenceError) } // === Public API (u64 scaled by 1e6) === @@ -195,33 +198,33 @@ pub fn get_swap_amount( current_reserve_no: u64, initial_liquidity: u64, amount_in: u64, -) -> u64 { +) -> Result { let ry = u64_to_q(current_reserve_yes).max(Q_MIN_RESERVE); let rn = u64_to_q(current_reserve_no).max(Q_MIN_RESERVE); let l = u64_to_q(initial_liquidity); let amt = u64_to_q(amount_in); let amount_out = if yes_to_no { - q_abs(rn - get_new_reserve_q(rn, ry + amt, l)) + q_abs(rn - get_new_reserve_q(rn, ry + amt, l)?) } else { - q_abs(ry - get_new_reserve_q(ry, rn + amt, l)) + q_abs(ry - get_new_reserve_q(ry, rn + amt, l)?) }; - q_to_u64(amount_out) + Ok(q_to_u64(amount_out)) } -pub fn calc_price(x: u64, y: u64, l: u64) -> u64 { +pub fn calc_price(x: u64, y: u64, l: u64) -> Result { let rx = u64_to_q(x); let ry = u64_to_q(y); let lq = u64_to_q(l); - if lq == 0 { return 500_000; } // Default 50% if no liquidity + if lq == 0 { return Ok(500_000); } // Default 50% if no liquidity - let z = q_div(ry - rx, lq); - let price = gaussian_cdf_q(z); + let z = q_div(ry - rx, lq)?; + let price = gaussian_cdf_q(z)?; // Scale to 1_000_000 basis points - ((price * 1_000_000i128) >> FRAC_BITS) as u64 + Ok(((price * 1_000_000i128) >> FRAC_BITS) as u64) } pub fn calc_liquidity(liquidity: u64, deadline: i64, current_time: i64) -> u64 { @@ -271,14 +274,14 @@ mod tests { #[test] fn test_calc_price_equal_reserves() { // Equal reserves → z=0 → CDF(0) = 0.5 → price = 500_000 - let price = calc_price(1_000_000, 1_000_000, 1_000_000); + let price = calc_price(1_000_000, 1_000_000, 1_000_000).unwrap(); // Allow ±1% tolerance assert!(price >= 490_000 && price <= 510_000, "price={}", price); } #[test] fn test_get_swap_amount_nonzero() { - let amt_out = get_swap_amount(true, 1_000_000, 1_000_000, 1_000_000, 100_000); + let amt_out = get_swap_amount(true, 1_000_000, 1_000_000, 1_000_000, 100_000).unwrap(); assert!(amt_out > 0, "swap should produce output"); } @@ -302,8 +305,8 @@ mod tests { #[test] fn test_swap_symmetry() { // Swapping yes→no and no→yes with equal reserves should give same output - let out1 = get_swap_amount(true, 1_000_000, 1_000_000, 1_000_000, 100_000); - let out2 = get_swap_amount(false, 1_000_000, 1_000_000, 1_000_000, 100_000); + let out1 = get_swap_amount(true, 1_000_000, 1_000_000, 1_000_000, 100_000).unwrap(); + let out2 = get_swap_amount(false, 1_000_000, 1_000_000, 1_000_000, 100_000).unwrap(); // Should be equal (within rounding) let diff = if out1 > out2 { out1 - out2 } else { out2 - out1 }; assert!(diff <= 1, "symmetry broken: out1={}, out2={}", out1, out2); @@ -326,7 +329,7 @@ mod tests { let b = (456_i128 << 32) + (1_i128 << 31); let expected = (a * b) >> FRAC_BITS; - assert_eq!(q_mul(a, b), expected); + assert_eq!(q_mul(a, b).unwrap(), expected); assert_ne!((a >> 32) * (b >> 32), expected); } @@ -336,6 +339,6 @@ mod tests { let denominator = (7_i128 << 32) + (1_i128 << 31); let expected = (numerator << FRAC_BITS) / denominator; - assert_eq!(q_div(numerator, denominator), expected); + assert_eq!(q_div(numerator, denominator).unwrap(), expected); } } diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/bet.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/bet.rs index 0aaab4d8..c014cb77 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/bet.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/bet.rs @@ -6,6 +6,7 @@ pub struct Bet { pub initial_liq: u64, // Initial Liquidity exactly matching EVM model pub is_dynamic: bool, pub reserves: [u64; 2], // 0 for Yes, 1 for No. These are virtual reserves. + pub duel_key: [u8; 32], pub bet_prompt: String, pub is_initialized: bool, // by default none @@ -15,6 +16,4 @@ pub struct Bet { pub creator: Pubkey, pub treasury: Pubkey, pub fee_bps: u16, - /// Full 32-byte duel key for oracle cross-reference (0 if not set) - pub duel_key: [u8; 32], } diff --git a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/config.rs b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/config.rs index 221b6a91..7d24b812 100644 --- a/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/config.rs +++ b/packages/hyperbet-solana/anchor/programs/lvr_amm/src/state/config.rs @@ -6,6 +6,7 @@ pub struct AmmConfig { pub authority: Pubkey, pub treasury: Pubkey, pub market_maker: Pubkey, + pub fight_oracle_program: Pubkey, pub fee_bps: u16, pub config_frozen: bool, pub paused: bool, diff --git a/packages/hyperbet-solana/anchor/scripts/build-workspace.sh b/packages/hyperbet-solana/anchor/scripts/build-workspace.sh index 0099d5ad..031f3026 100755 --- a/packages/hyperbet-solana/anchor/scripts/build-workspace.sh +++ b/packages/hyperbet-solana/anchor/scripts/build-workspace.sh @@ -10,6 +10,7 @@ PROGRAMS=( "fight_oracle" "gold_clob_market" "gold_perps_market" + "lvr_amm" ) extract_marker_json() { diff --git a/packages/hyperbet-solana/anchor/scripts/run-localnet-tests.sh b/packages/hyperbet-solana/anchor/scripts/run-localnet-tests.sh index cbec702d..d05b5606 100755 --- a/packages/hyperbet-solana/anchor/scripts/run-localnet-tests.sh +++ b/packages/hyperbet-solana/anchor/scripts/run-localnet-tests.sh @@ -170,7 +170,7 @@ if [[ ! -x "$ROOT_DIR/node_modules/.bin/ts-mocha" ]]; then exit 1 fi -if [[ ! -f "$ROOT_DIR/target/deploy/fight_oracle.so" || ! -f "$ROOT_DIR/target/deploy/gold_clob_market.so" || ! -f "$ROOT_DIR/target/deploy/gold_perps_market.so" ]]; then +if [[ ! -f "$ROOT_DIR/target/deploy/fight_oracle.so" || ! -f "$ROOT_DIR/target/deploy/gold_clob_market.so" || ! -f "$ROOT_DIR/target/deploy/gold_perps_market.so" || ! -f "$ROOT_DIR/target/deploy/lvr_amm.so" ]]; then printf 'Missing one or more deploy artifacts under %s\n' "$ROOT_DIR/target/deploy" >&2 exit 1 fi @@ -191,6 +191,7 @@ MINT_AUTHORITY="$(resolve_mint_authority "$WALLET_PATH")" PROGRAM_ORACLE_ID="$(resolve_program_id fight_oracle B5mRCRDJk9BrnH7regMWW5mpTQ8QG1CcCGSnDxMt8hmo)" PROGRAM_CLOB_ID="$(resolve_program_id gold_clob_market DYtd7AoyTX2tbmZ8vpC3mxZgqTpyaDei4TFXZukWBJEf)" PROGRAM_PERPS_ID="$(resolve_program_id gold_perps_market EoZdHN8U3qWQje48ToxB1SLWjucsFGqcWaRUJQYX3eoT)" +PROGRAM_LVR_AMM_ID="$(resolve_program_id lvr_amm Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5)" : >"$TEST_LOG" @@ -220,6 +221,7 @@ for test_target in "${TEST_TARGETS[@]}"; do --upgradeable-program "$PROGRAM_ORACLE_ID" "$ROOT_DIR/target/deploy/fight_oracle.so" "$WALLET_PATH" \ --upgradeable-program "$PROGRAM_CLOB_ID" "$ROOT_DIR/target/deploy/gold_clob_market.so" "$WALLET_PATH" \ --upgradeable-program "$PROGRAM_PERPS_ID" "$ROOT_DIR/target/deploy/gold_perps_market.so" "$WALLET_PATH" \ + --upgradeable-program "$PROGRAM_LVR_AMM_ID" "$ROOT_DIR/target/deploy/lvr_amm.so" "$WALLET_PATH" \ >"$VALIDATOR_LOG" 2>&1 & VALIDATOR_PID="$!" @@ -229,7 +231,7 @@ for test_target in "${TEST_TARGETS[@]}"; do exit 1 fi - for program_id in "$PROGRAM_ORACLE_ID" "$PROGRAM_CLOB_ID" "$PROGRAM_PERPS_ID"; do + for program_id in "$PROGRAM_ORACLE_ID" "$PROGRAM_CLOB_ID" "$PROGRAM_PERPS_ID" "$PROGRAM_LVR_AMM_ID"; do if ! wait_for_program "$current_rpc_url" "$program_id"; then echo "[anchor-test] program $program_id did not become executable" >&2 tail -n 120 "$VALIDATOR_LOG" >&2 || true diff --git a/packages/hyperbet-solana/anchor/target/deploy/lvr_amm-keypair.json b/packages/hyperbet-solana/anchor/target/deploy/lvr_amm-keypair.json new file mode 100644 index 00000000..618a8edf --- /dev/null +++ b/packages/hyperbet-solana/anchor/target/deploy/lvr_amm-keypair.json @@ -0,0 +1 @@ +[63,251,97,153,164,205,165,201,109,58,150,237,78,77,245,209,95,248,195,221,18,192,22,12,206,148,35,66,103,208,27,18,76,169,46,200,60,213,139,25,2,99,87,237,223,81,243,188,170,170,146,171,175,65,87,193,118,219,235,73,118,32,55,127] \ No newline at end of file diff --git a/packages/hyperbet-solana/anchor/target/deploy/lvr_amm.so b/packages/hyperbet-solana/anchor/target/deploy/lvr_amm.so new file mode 100755 index 00000000..a72067f9 Binary files /dev/null and b/packages/hyperbet-solana/anchor/target/deploy/lvr_amm.so differ diff --git a/packages/hyperbet-solana/anchor/target/idl/lvr_amm.json b/packages/hyperbet-solana/anchor/target/idl/lvr_amm.json index fd2efa13..a42286e7 100644 --- a/packages/hyperbet-solana/anchor/target/idl/lvr_amm.json +++ b/packages/hyperbet-solana/anchor/target/idl/lvr_amm.json @@ -735,6 +735,10 @@ "name": "market_maker", "type": "pubkey" }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, { "name": "fee_bps", "type": "u16" @@ -1190,6 +1194,32 @@ ] } }, + { + "name": "amm_config", + "docs": [ + "Optional: AmmConfig for oracle program ID validation (required when duel_state is provided)" + ], + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, { "name": "duel_state", "docs": [ @@ -1700,23 +1730,68 @@ }, { "code": 6016, + "name": "MathOverflow", + "msg": "Arithmetic overflow" + }, + { + "code": 6017, + "name": "InsufficientReserves", + "msg": "Insufficient reserves for swap" + }, + { + "code": 6018, + "name": "MarketExpired", + "msg": "Market has expired" + }, + { + "code": 6019, + "name": "InvalidSettlementOutcome", + "msg": "Invalid settlement outcome" + }, + { + "code": 6020, "name": "InvalidAddress", "msg": "Invalid address (zero/default)" }, { - "code": 6017, + "code": 6021, "name": "FeeTooHigh", "msg": "Fee BPS exceeds maximum (1000 = 10%)" }, { - "code": 6018, + "code": 6022, "name": "MarketPaused", "msg": "Market is paused" }, { - "code": 6019, + "code": 6023, "name": "ConfigFrozen", "msg": "Config is frozen" + }, + { + "code": 6024, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6025, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6026, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + }, + { + "code": 6027, + "name": "MathConvergenceError", + "msg": "AMM Newton-Raphson solver did not converge" + }, + { + "code": 6028, + "name": "MathFixedPointOverflow", + "msg": "AMM fixed-point overflow" } ], "types": [ @@ -1769,6 +1844,10 @@ "name": "market_maker", "type": "pubkey" }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, { "name": "fee_bps", "type": "u16" @@ -1813,6 +1892,10 @@ "name": "treasury", "type": "pubkey" }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, { "name": "fee_bps", "type": "u16" @@ -1858,6 +1941,15 @@ ] } }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "bet_prompt", "type": "string" @@ -1891,18 +1983,6 @@ { "name": "fee_bps", "type": "u16" - }, - { - "name": "duel_key", - "docs": [ - "Full 32-byte duel key for oracle cross-reference (0 if not set)" - ], - "type": { - "array": [ - "u8", - 32 - ] - } } ] } diff --git a/packages/hyperbet-solana/anchor/target/types/lvr_amm.ts b/packages/hyperbet-solana/anchor/target/types/lvr_amm.ts index cb0aae0a..d1a19933 100644 --- a/packages/hyperbet-solana/anchor/target/types/lvr_amm.ts +++ b/packages/hyperbet-solana/anchor/target/types/lvr_amm.ts @@ -501,6 +501,15 @@ export type LvrAmm = { { "name": "expirationAt", "type": "i64" + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } } ] }, @@ -732,6 +741,10 @@ export type LvrAmm = { "name": "marketMaker", "type": "pubkey" }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, { "name": "feeBps", "type": "u16" @@ -1187,6 +1200,32 @@ export type LvrAmm = { ] } }, + { + "name": "ammConfig", + "docs": [ + "Optional: AmmConfig for oracle program ID validation (required when duel_state is provided)" + ], + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, { "name": "duelState", "docs": [ @@ -1697,23 +1736,68 @@ export type LvrAmm = { }, { "code": 6016, + "name": "mathOverflow", + "msg": "Arithmetic overflow" + }, + { + "code": 6017, + "name": "insufficientReserves", + "msg": "Insufficient reserves for swap" + }, + { + "code": 6018, + "name": "marketExpired", + "msg": "Market has expired" + }, + { + "code": 6019, + "name": "invalidSettlementOutcome", + "msg": "Invalid settlement outcome" + }, + { + "code": 6020, "name": "invalidAddress", "msg": "Invalid address (zero/default)" }, { - "code": 6017, + "code": 6021, "name": "feeTooHigh", "msg": "Fee BPS exceeds maximum (1000 = 10%)" }, { - "code": 6018, + "code": 6022, "name": "marketPaused", "msg": "Market is paused" }, { - "code": 6019, + "code": 6023, "name": "configFrozen", "msg": "Config is frozen" + }, + { + "code": 6024, + "name": "invalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6025, + "name": "missingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6026, + "name": "invalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + }, + { + "code": 6027, + "name": "mathConvergenceError", + "msg": "AMM Newton-Raphson solver did not converge" + }, + { + "code": 6028, + "name": "mathFixedPointOverflow", + "msg": "AMM fixed-point overflow" } ], "types": [ @@ -1766,6 +1850,10 @@ export type LvrAmm = { "name": "marketMaker", "type": "pubkey" }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, { "name": "feeBps", "type": "u16" @@ -1810,6 +1898,10 @@ export type LvrAmm = { "name": "treasury", "type": "pubkey" }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, { "name": "feeBps", "type": "u16" @@ -1855,6 +1947,15 @@ export type LvrAmm = { ] } }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "betPrompt", "type": "string" diff --git a/packages/hyperbet-solana/anchor/tests/amm-test-helpers.ts b/packages/hyperbet-solana/anchor/tests/amm-test-helpers.ts index a2e29e80..1d04469f 100644 --- a/packages/hyperbet-solana/anchor/tests/amm-test-helpers.ts +++ b/packages/hyperbet-solana/anchor/tests/amm-test-helpers.ts @@ -160,6 +160,9 @@ export async function ensureOracleReady( program: Program, authority: Keypair, reporter = authority.publicKey, + finalizer = authority.publicKey, + challenger = authority.publicKey, + disputeWindowSecs = 60, ): Promise { const oracleConfig = deriveOracleConfigPda(program.programId); const existingConfig = @@ -167,7 +170,12 @@ export async function ensureOracleReady( if (!existingConfig) { await program.methods - .initializeOracle(reporter) + .initializeOracle( + reporter, + finalizer, + challenger, + new BN(disputeWindowSecs), + ) .accountsPartial({ authority: authority.publicKey, oracleConfig, @@ -181,7 +189,13 @@ export async function ensureOracleReady( } await program.methods - .updateOracleConfig(authority.publicKey, reporter) + .updateOracleConfig( + authority.publicKey, + reporter, + finalizer, + challenger, + new BN(disputeWindowSecs), + ) .accountsPartial({ authority: authority.publicKey, oracleConfig, @@ -205,7 +219,7 @@ export async function ensureLvrAdmin( ): Promise { const adminState = deriveAdminStatePda(program.programId); const existingConfig = - await program.account.admin.fetchNullable(adminState); + await (program.account as any).admin.fetchNullable(adminState); if (!existingConfig) { await program.methods @@ -224,18 +238,20 @@ export async function ensureLvrAdmin( export async function ensureAmmConfig( program: Program, authority: Keypair, + fightOracleProgramId: PublicKey, treasury?: PublicKey, feeBps = 200, ): Promise { const ammConfig = deriveAmmConfigPda(program.programId); const existingConfig = - await program.account.ammConfig.fetchNullable(ammConfig); + await (program.account as any).ammConfig.fetchNullable(ammConfig); if (!existingConfig) { await program.methods .initializeConfig( treasury ?? authority.publicKey, authority.publicKey, // market_maker + fightOracleProgramId, feeBps, ) .accountsPartial({ @@ -336,22 +352,22 @@ export async function reportDuelResult( const oracleConfig = deriveOracleConfigPda(program.programId); const duelState = deriveDuelStatePda(program.programId, duelKey); - await program.methods - .reportResult( - [...duelKey], - options.winner, - toBn(options.seed ?? 42), - [ - ...(options.replayHash ?? - hashLabel(`${Buffer.from(duelKey).toString("hex")}:replay`)), - ], - [ - ...(options.resultHash ?? - hashLabel(`${Buffer.from(duelKey).toString("hex")}:result`)), - ], - toBn(options.duelEndTs), - options.metadataUri ?? "https://hyperscape.gg/duels/result", - ) + const builder: any = (program as any).methods.proposeResult( + [...duelKey], + options.winner, + toBn(options.seed ?? 42), + [ + ...(options.replayHash ?? + hashLabel(`${Buffer.from(duelKey).toString("hex")}:replay`)), + ], + [ + ...(options.resultHash ?? + hashLabel(`${Buffer.from(duelKey).toString("hex")}:result`)), + ], + toBn(options.duelEndTs), + options.metadataUri ?? "https://hyperscape.gg/duels/result", + ); + await builder .accountsPartial({ reporter: reporter.publicKey, oracleConfig, @@ -389,7 +405,7 @@ export async function initializeCanonicalMarket( const expirationAt = new BN(Date.now() / 1000 + 3600); await program.methods - .createBetAccount(betId, initialLiq, isDynamic, description, expirationAt) + .createBetAccount(betId, initialLiq, isDynamic, [...duelKey], description, expirationAt) .accountsPartial({ signer: operator.publicKey, ammConfig, @@ -453,7 +469,7 @@ export async function placeClobOrder( order: PublicKey; restingLevel: PublicKey; }> { - const bet = await program.account.bet.fetch(args.marketState); + const bet = await (program.account as any).bet.fetch(args.marketState); const betId = bet.betId; const creator = bet.creator; @@ -530,7 +546,7 @@ export async function claimClobWinnings( user: Keypair; }, ): Promise { - const bet = await program.account.bet.fetch(args.marketState); + const bet = await (program.account as any).bet.fetch(args.marketState); const betId = bet.betId; const creator = bet.creator; @@ -540,30 +556,40 @@ export async function claimClobWinnings( const srcNo = getAssociatedTokenAddressSync(mintNo, args.user.publicKey, true); // In tests, claim everything on the winning side - const infoYes = await program.provider.connection.getAccountInfo(srcYes); - const infoNo = await program.provider.connection.getAccountInfo(srcNo); const balYes = await program.provider.connection.getTokenAccountBalance(srcYes).catch(() => ({ value: { amount: "0" }})); const balNo = await program.provider.connection.getTokenAccountBalance(srcNo).catch(() => ({ value: { amount: "0" }})); - - const hasYes = BigInt(balYes.value.amount) > 0; - const outcome = hasYes ? 0 : 1; - const qStr = hasYes ? balYes.value.amount : balNo.value.amount; - - await program.methods - .withdrawPostSettle(betId, outcome, new BN(qStr)) - .accountsPartial({ - signer: args.user.publicKey, - bet: args.marketState, - mintYes, - mintNo, - destinationYes: srcYes, - destinationNo: srcNo, - tokenProgram: TOKEN_PROGRAM_ID, - systemProgram: SystemProgram.programId, - associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, - }) - .signers([args.user]) - .rpc(); + + const withdrawals: Array<{ outcome: 0 | 1; amount: string }> = []; + const sideWon = bet.sideWon == null ? null : Number(bet.sideWon); + const hasYes = BigInt(balYes.value.amount) > 0n; + const hasNo = BigInt(balNo.value.amount) > 0n; + + if (sideWon === 2) { + if (hasYes) withdrawals.push({ outcome: 0, amount: balYes.value.amount }); + if (hasNo) withdrawals.push({ outcome: 1, amount: balNo.value.amount }); + } else if (hasYes) { + withdrawals.push({ outcome: 0, amount: balYes.value.amount }); + } else if (hasNo) { + withdrawals.push({ outcome: 1, amount: balNo.value.amount }); + } + + for (const withdrawal of withdrawals) { + await program.methods + .withdrawPostSettle(betId, withdrawal.outcome, new BN(withdrawal.amount)) + .accountsPartial({ + signer: args.user.publicKey, + bet: args.marketState, + mintYes, + mintNo, + destinationYes: srcYes, + destinationNo: srcNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([args.user]) + .rpc(); + } return srcYes; } @@ -598,7 +624,12 @@ export async function createOpenMarketFixture( await ensureOracleReady(fightProgram, authority, authority.publicKey); await ensureLvrAdmin(clobProgram, authority); - const config = await ensureAmmConfig(clobProgram, authority, treasury); + const config = await ensureAmmConfig( + clobProgram, + authority, + fightProgram.programId, + treasury, + ); const duelState = await upsertDuel(fightProgram, authority, duelKey, { status: duelStatusBettingOpen(), betOpenTs: options?.betOpenTs ?? now - 30, diff --git a/packages/hyperbet-solana/anchor/tests/lvr_amm_security.test.ts b/packages/hyperbet-solana/anchor/tests/lvr_amm_security.test.ts new file mode 100644 index 00000000..e83c8b2d --- /dev/null +++ b/packages/hyperbet-solana/anchor/tests/lvr_amm_security.test.ts @@ -0,0 +1,555 @@ +import * as anchor from "@coral-xyz/anchor"; +import { Program } from "@coral-xyz/anchor"; +import * as assert from "assert"; +import BN from "bn.js"; +import { + ASSOCIATED_TOKEN_PROGRAM_ID, + createAssociatedTokenAccountInstruction, + getAssociatedTokenAddressSync, + TOKEN_PROGRAM_ID, +} from "@solana/spl-token"; +import { + Keypair, + PublicKey, + SystemProgram, + Transaction, +} from "@solana/web3.js"; + +import { FightOracle } from "../target/types/fight_oracle"; +import { LvrAmm } from "../target/types/lvr_amm"; +import { + airdrop, + cancelDuel, + deriveAdminStatePda, + deriveAmmConfigPda, + deriveBetPda, + deriveDuelStatePda, + deriveMintNoPda, + deriveMintYesPda, + duelStatusBettingOpen, + ensureAmmConfig, + ensureLvrAdmin, + ensureOracleReady, + hasProgramError, + uniqueDuelKey, + upsertDuel, +} from "./amm-test-helpers"; +import { configureAnchorTests } from "./test-anchor"; + +const provider = configureAnchorTests(); +anchor.setProvider(provider); + +const fightProgram = anchor.workspace.FightOracle as Program; +const ammProgram = anchor.workspace.LvrAmm as Program; +const authority = (provider.wallet as anchor.Wallet & { payer: Keypair }).payer; + +function betIdFromDuelKey(duelKey: readonly number[]): bigint { + return BigInt( + `0x${Buffer.from(duelKey).slice(0, 8).reverse().toString("hex")}`, + ); +} + +async function ensureAta( + mint: PublicKey, + owner: PublicKey, + payer: Keypair, +): Promise { + const ata = getAssociatedTokenAddressSync(mint, owner, true); + const existing = await provider.connection.getAccountInfo(ata); + if (existing) return ata; + + const tx = new Transaction().add( + createAssociatedTokenAccountInstruction( + payer.publicKey, + ata, + owner, + mint, + ), + ); + await provider.sendAndConfirm(tx, [payer]); + return ata; +} + +async function waitUntilAfter(unixTs: number): Promise { + while (Math.floor(Date.now() / 1000) <= unixTs) { + await new Promise((resolve) => setTimeout(resolve, 250)); + } +} + +async function createBetFixture(options?: { + creator?: Keypair; + duelKey?: readonly number[]; + expirationOffsetSecs?: number; + initialized?: boolean; + initialLiqLamports?: number; + isDynamic?: boolean; + treasury?: PublicKey; +}): Promise<{ + adminState: PublicKey; + ammConfig: PublicKey; + bet: PublicKey; + mintYes: PublicKey; + mintNo: PublicKey; + betId: BN; + betIdBigInt: bigint; + duelKey: number[]; + creator: Keypair; + treasury: PublicKey; + expirationAt: number; +}> { + const creator = options?.creator ?? Keypair.generate(); + const duelKey = [...(options?.duelKey ?? uniqueDuelKey("lvr-amm-security"))]; + const treasury = options?.treasury ?? authority.publicKey; + const betIdBigInt = betIdFromDuelKey(duelKey); + const betId = new BN(betIdBigInt.toString()); + const bet = deriveBetPda(ammProgram.programId, betIdBigInt, creator.publicKey); + const mintYes = deriveMintYesPda( + ammProgram.programId, + betIdBigInt, + creator.publicKey, + ); + const mintNo = deriveMintNoPda( + ammProgram.programId, + betIdBigInt, + creator.publicKey, + ); + const expirationAt = + Math.floor(Date.now() / 1000) + (options?.expirationOffsetSecs ?? 60); + + await airdrop(provider.connection, creator.publicKey, 10); + await ensureOracleReady( + fightProgram, + authority, + authority.publicKey, + authority.publicKey, + authority.publicKey, + 60, + ); + const adminState = await ensureLvrAdmin(ammProgram, authority); + const ammConfig = await ensureAmmConfig( + ammProgram, + authority, + fightProgram.programId, + treasury, + ); + + await ammProgram.methods + .createBetAccount( + betId, + new BN(options?.initialLiqLamports ?? 5_000_000), + options?.isDynamic ?? false, + [...duelKey], + "LVR AMM security fixture", + new BN(expirationAt), + ) + .accountsPartial({ + signer: creator.publicKey, + ammConfig, + bet, + mintYes, + mintNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + }) + .signers([creator]) + .rpc(); + + if (options?.initialized ?? true) { + await ammProgram.methods + .initBetAccount(betId) + .accountsPartial({ + signer: creator.publicKey, + bet, + systemProgram: SystemProgram.programId, + }) + .signers([creator]) + .rpc(); + } + + return { + adminState, + ammConfig, + bet, + mintYes, + mintNo, + betId, + betIdBigInt, + duelKey, + creator, + treasury, + expirationAt, + }; +} + +describe("lvr_amm security", () => { + it("rejects settlement with a duel PDA derived from a different duel key", async () => { + const fixture = await createBetFixture({ expirationOffsetSecs: -60 }); + const now = Math.floor(Date.now() / 1000); + const otherDuelKey = uniqueDuelKey("wrong-duel"); + const wrongDuelState = deriveDuelStatePda(fightProgram.programId, otherDuelKey); + + await upsertDuel(fightProgram, authority, otherDuelKey, { + status: duelStatusBettingOpen(), + betOpenTs: now - 120, + betCloseTs: now - 60, + duelStartTs: now - 30, + metadataUri: "https://tests/wrong-duel", + }); + await cancelDuel(fightProgram, authority, otherDuelKey); + + try { + await ammProgram.methods + .settleBet(fixture.betId, 0) + .accountsPartial({ + signer: authority.publicKey, + ammConfig: fixture.ammConfig, + adminState: fixture.adminState, + bet: fixture.bet, + duelState: wrongDuelState, + }) + .signers([authority]) + .rpc(); + assert.fail("settle_bet accepted an unrelated duel PDA"); + } catch (error: unknown) { + assert.ok( + hasProgramError(error, "Invalid duel state account"), + `expected Invalid duel state account, got ${String(error)}`, + ); + } + }); + + it("rejects settlement with a duel account owned by the wrong program", async () => { + const fixture = await createBetFixture({ expirationOffsetSecs: -60 }); + + try { + await ammProgram.methods + .settleBet(fixture.betId, 0) + .accountsPartial({ + signer: authority.publicKey, + ammConfig: fixture.ammConfig, + adminState: fixture.adminState, + bet: fixture.bet, + duelState: fixture.bet, + }) + .signers([authority]) + .rpc(); + assert.fail("settle_bet accepted a non-oracle-owned account"); + } catch (error: unknown) { + assert.ok( + hasProgramError(error, "Fight oracle program mismatch"), + `expected Fight oracle program mismatch, got ${String(error)}`, + ); + } + }); + + it("rejects buys before init_bet_account funds the bet", async () => { + const creator = Keypair.generate(); + const buyer = Keypair.generate(); + const fixture = await createBetFixture({ + creator, + initialized: false, + expirationOffsetSecs: 300, + }); + + await airdrop(provider.connection, buyer.publicKey, 5); + const destinationYes = await ensureAta(fixture.mintYes, buyer.publicKey, buyer); + const destinationNo = await ensureAta(fixture.mintNo, buyer.publicKey, buyer); + + try { + await ammProgram.methods + .buy(fixture.betId, 0, new BN(100_000)) + .accountsPartial({ + signer: buyer.publicKey, + ammConfig: fixture.ammConfig, + bet: fixture.bet, + treasury: fixture.treasury, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + assert.fail("buy succeeded before init_bet_account"); + } catch (error: unknown) { + assert.ok( + hasProgramError(error, "Bet not initialized"), + `expected Bet not initialized, got ${String(error)}`, + ); + } + }); + + it("allows YES holders to redeem 1:1 after a cancelled oracle duel", async () => { + const buyer = Keypair.generate(); + const fixture = await createBetFixture({ expirationOffsetSecs: 15 }); + await airdrop(provider.connection, buyer.publicKey, 5); + const destinationYes = await ensureAta(fixture.mintYes, buyer.publicKey, buyer); + const destinationNo = await ensureAta(fixture.mintNo, buyer.publicKey, buyer); + + await ammProgram.methods + .buy(fixture.betId, 0, new BN(100_000)) + .accountsPartial({ + signer: buyer.publicKey, + ammConfig: fixture.ammConfig, + bet: fixture.bet, + treasury: fixture.treasury, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + + const now = Math.floor(Date.now() / 1000); + await upsertDuel(fightProgram, authority, fixture.duelKey, { + status: duelStatusBettingOpen(), + betOpenTs: now - 120, + betCloseTs: now - 60, + duelStartTs: now - 30, + metadataUri: "https://tests/cancel-yes", + }); + await cancelDuel(fightProgram, authority, fixture.duelKey); + await waitUntilAfter(fixture.expirationAt); + + const duelState = deriveDuelStatePda(fightProgram.programId, fixture.duelKey); + await ammProgram.methods + .settleBet(fixture.betId, 0) + .accountsPartial({ + signer: authority.publicKey, + ammConfig: fixture.ammConfig, + adminState: fixture.adminState, + bet: fixture.bet, + duelState, + }) + .signers([authority]) + .rpc(); + + const yesBalance = await provider.connection.getTokenAccountBalance(destinationYes); + const q = Number(yesBalance.value.amount); + const betBalanceBefore = await provider.connection.getBalance(fixture.bet); + + await ammProgram.methods + .withdrawPostSettle(fixture.betId, 0, new BN(q)) + .accountsPartial({ + signer: buyer.publicKey, + bet: fixture.bet, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + + const betBalanceAfter = await provider.connection.getBalance(fixture.bet); + const yesBalanceAfter = await provider.connection.getTokenAccountBalance(destinationYes); + assert.strictEqual(betBalanceBefore - betBalanceAfter, q); + assert.strictEqual(Number(yesBalanceAfter.value.amount), 0); + }); + + it("allows NO holders to redeem 1:1 after a cancelled oracle duel", async () => { + const buyer = Keypair.generate(); + const fixture = await createBetFixture({ expirationOffsetSecs: 15 }); + await airdrop(provider.connection, buyer.publicKey, 5); + const destinationYes = await ensureAta(fixture.mintYes, buyer.publicKey, buyer); + const destinationNo = await ensureAta(fixture.mintNo, buyer.publicKey, buyer); + + await ammProgram.methods + .buy(fixture.betId, 1, new BN(100_000)) + .accountsPartial({ + signer: buyer.publicKey, + ammConfig: fixture.ammConfig, + bet: fixture.bet, + treasury: fixture.treasury, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + + const now = Math.floor(Date.now() / 1000); + await upsertDuel(fightProgram, authority, fixture.duelKey, { + status: duelStatusBettingOpen(), + betOpenTs: now - 120, + betCloseTs: now - 60, + duelStartTs: now - 30, + metadataUri: "https://tests/cancel-no", + }); + await cancelDuel(fightProgram, authority, fixture.duelKey); + await waitUntilAfter(fixture.expirationAt); + + const duelState = deriveDuelStatePda(fightProgram.programId, fixture.duelKey); + await ammProgram.methods + .settleBet(fixture.betId, 0) + .accountsPartial({ + signer: authority.publicKey, + ammConfig: fixture.ammConfig, + adminState: fixture.adminState, + bet: fixture.bet, + duelState, + }) + .signers([authority]) + .rpc(); + + const noBalance = await provider.connection.getTokenAccountBalance(destinationNo); + const q = Number(noBalance.value.amount); + const betBalanceBefore = await provider.connection.getBalance(fixture.bet); + + await ammProgram.methods + .withdrawPostSettle(fixture.betId, 1, new BN(q)) + .accountsPartial({ + signer: buyer.publicKey, + bet: fixture.bet, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + + const betBalanceAfter = await provider.connection.getBalance(fixture.bet); + const noBalanceAfter = await provider.connection.getTokenAccountBalance(destinationNo); + assert.strictEqual(betBalanceBefore - betBalanceAfter, q); + assert.strictEqual(Number(noBalanceAfter.value.amount), 0); + }); + + it("rejects sells when the treasury ATA is not owned by bet.treasury", async () => { + const buyer = Keypair.generate(); + const fixture = await createBetFixture({ expirationOffsetSecs: 300 }); + await airdrop(provider.connection, buyer.publicKey, 5); + const destinationYes = await ensureAta(fixture.mintYes, buyer.publicKey, buyer); + const destinationNo = await ensureAta(fixture.mintNo, buyer.publicKey, buyer); + const treasuryNoAta = await ensureAta( + fixture.mintNo, + fixture.treasury, + authority, + ); + await ammProgram.methods + .buy(fixture.betId, 0, new BN(100_000)) + .accountsPartial({ + signer: buyer.publicKey, + ammConfig: fixture.ammConfig, + bet: fixture.bet, + treasury: fixture.treasury, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + + try { + await ammProgram.methods + .sell(fixture.betId, 0, new BN(1)) + .accountsStrict({ + signer: buyer.publicKey, + ammConfig: fixture.ammConfig, + bet: fixture.bet, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + treasury: fixture.treasury, + treasuryYesAta: destinationYes, + treasuryNoAta, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + assert.fail("sell accepted a treasury ATA owned by the trader"); + } catch (error: unknown) { + assert.ok( + hasProgramError(error, "ConstraintTokenOwner"), + `expected token owner constraint failure, got ${String(error)}`, + ); + } + }); + + it("rejects sells when the treasury ATA mint does not match the fee side mint", async () => { + const buyer = Keypair.generate(); + const fixture = await createBetFixture({ expirationOffsetSecs: 300 }); + await airdrop(provider.connection, buyer.publicKey, 5); + const destinationYes = await ensureAta(fixture.mintYes, buyer.publicKey, buyer); + const destinationNo = await ensureAta(fixture.mintNo, buyer.publicKey, buyer); + const treasuryYesAta = await ensureAta( + fixture.mintYes, + fixture.treasury, + authority, + ); + const treasuryNoAta = await ensureAta( + fixture.mintNo, + fixture.treasury, + authority, + ); + await ammProgram.methods + .buy(fixture.betId, 0, new BN(100_000)) + .accountsPartial({ + signer: buyer.publicKey, + ammConfig: fixture.ammConfig, + bet: fixture.bet, + treasury: fixture.treasury, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + + try { + await ammProgram.methods + .sell(fixture.betId, 0, new BN(1)) + .accountsStrict({ + signer: buyer.publicKey, + ammConfig: fixture.ammConfig, + bet: fixture.bet, + mintYes: fixture.mintYes, + mintNo: fixture.mintNo, + destinationYes, + destinationNo, + treasury: fixture.treasury, + treasuryYesAta: treasuryNoAta, + treasuryNoAta: treasuryYesAta, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .signers([buyer]) + .rpc(); + assert.fail("sell accepted a treasury ATA for the wrong mint"); + } catch (error: unknown) { + assert.ok( + hasProgramError(error, "ConstraintAssociated"), + `expected associated-token constraint failure, got ${String(error)}`, + ); + } + }); +}); diff --git a/packages/hyperbet-solana/app/src/idl/lvr_amm.json b/packages/hyperbet-solana/app/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/hyperbet-solana/app/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/hyperbet-solana/app/src/idl/lvr_amm.ts b/packages/hyperbet-solana/app/src/idl/lvr_amm.ts index 8524b9ec..d1a19933 100644 --- a/packages/hyperbet-solana/app/src/idl/lvr_amm.ts +++ b/packages/hyperbet-solana/app/src/idl/lvr_amm.ts @@ -741,6 +741,10 @@ export type LvrAmm = { "name": "marketMaker", "type": "pubkey" }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, { "name": "feeBps", "type": "u16" @@ -1196,6 +1200,32 @@ export type LvrAmm = { ] } }, + { + "name": "ammConfig", + "docs": [ + "Optional: AmmConfig for oracle program ID validation (required when duel_state is provided)" + ], + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, { "name": "duelState", "docs": [ @@ -1706,23 +1736,68 @@ export type LvrAmm = { }, { "code": 6016, + "name": "mathOverflow", + "msg": "Arithmetic overflow" + }, + { + "code": 6017, + "name": "insufficientReserves", + "msg": "Insufficient reserves for swap" + }, + { + "code": 6018, + "name": "marketExpired", + "msg": "Market has expired" + }, + { + "code": 6019, + "name": "invalidSettlementOutcome", + "msg": "Invalid settlement outcome" + }, + { + "code": 6020, "name": "invalidAddress", "msg": "Invalid address (zero/default)" }, { - "code": 6017, + "code": 6021, "name": "feeTooHigh", "msg": "Fee BPS exceeds maximum (1000 = 10%)" }, { - "code": 6018, + "code": 6022, "name": "marketPaused", "msg": "Market is paused" }, { - "code": 6019, + "code": 6023, "name": "configFrozen", "msg": "Config is frozen" + }, + { + "code": 6024, + "name": "invalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6025, + "name": "missingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6026, + "name": "invalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + }, + { + "code": 6027, + "name": "mathConvergenceError", + "msg": "AMM Newton-Raphson solver did not converge" + }, + { + "code": 6028, + "name": "mathFixedPointOverflow", + "msg": "AMM fixed-point overflow" } ], "types": [ @@ -1775,6 +1850,10 @@ export type LvrAmm = { "name": "marketMaker", "type": "pubkey" }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, { "name": "feeBps", "type": "u16" @@ -1819,6 +1898,10 @@ export type LvrAmm = { "name": "treasury", "type": "pubkey" }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, { "name": "feeBps", "type": "u16" @@ -1864,6 +1947,15 @@ export type LvrAmm = { ] } }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, { "name": "betPrompt", "type": "string" @@ -1897,18 +1989,6 @@ export type LvrAmm = { { "name": "feeBps", "type": "u16" - }, - { - "name": "duelKey", - "docs": [ - "Full 32-byte duel key for oracle cross-reference (0 if not set)" - ], - "type": { - "array": [ - "u8", - 32 - ] - } } ] } diff --git a/packages/hyperbet-solana/app/src/lib/config.ts b/packages/hyperbet-solana/app/src/lib/config.ts index e2638b8c..834b6fbe 100644 --- a/packages/hyperbet-solana/app/src/lib/config.ts +++ b/packages/hyperbet-solana/app/src/lib/config.ts @@ -132,6 +132,7 @@ function buildSolanaProgramConfig( | "fightOracleProgramId" | "goldClobMarketProgramId" | "goldPerpsMarketProgramId" + | "goldAmmMarketProgramId" | "goldMint" | "usdcMint" > { @@ -140,6 +141,7 @@ function buildSolanaProgramConfig( fightOracleProgramId: deployment.fightOracleProgramId, goldClobMarketProgramId: deployment.goldClobMarketProgramId, goldPerpsMarketProgramId: deployment.goldPerpsMarketProgramId, + goldAmmMarketProgramId: deployment.goldAmmMarketProgramId, goldMint: deployment.goldMint, usdcMint: deployment.usdcMint, }; @@ -152,6 +154,7 @@ export interface EnvConfig { fightOracleProgramId: string; goldClobMarketProgramId: string; goldPerpsMarketProgramId: string; + goldAmmMarketProgramId: string; goldMint: string; usdcMint?: string; betWindowSeconds: number; @@ -322,6 +325,9 @@ export const CONFIG: EnvConfig = { goldPerpsMarketProgramId: readEnvString("VITE_GOLD_PERPS_MARKET_PROGRAM_ID") ?? baseEnvConfig.goldPerpsMarketProgramId, + goldAmmMarketProgramId: + readEnvString("VITE_GOLD_AMM_MARKET_PROGRAM_ID") ?? + baseEnvConfig.goldAmmMarketProgramId, goldMint: readEnvString("VITE_GOLD_MINT") ?? baseEnvConfig.goldMint, usdcMint: readEnvString("VITE_USDC_MINT") ?? baseEnvConfig.usdcMint, betWindowSeconds: readEnvNumber( diff --git a/packages/hyperbet-solana/app/src/lib/programIds.ts b/packages/hyperbet-solana/app/src/lib/programIds.ts index 11293ab2..8104223a 100644 --- a/packages/hyperbet-solana/app/src/lib/programIds.ts +++ b/packages/hyperbet-solana/app/src/lib/programIds.ts @@ -42,3 +42,12 @@ export const GOLD_CLOB_MARKET_PROGRAM_ID = new PublicKey( export const GOLD_PERPS_MARKET_PROGRAM_ID = new PublicKey( goldPerpsMarketProgramAddress, ); + +export const goldAmmMarketProgramAddress = configuredAddress( + CONFIG.goldAmmMarketProgramId, + "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", +); + +export const GOLD_AMM_MARKET_PROGRAM_ID = new PublicKey( + goldAmmMarketProgramAddress, +); diff --git a/packages/hyperbet-solana/keeper/src/bot.ts b/packages/hyperbet-solana/keeper/src/bot.ts index 1e3603af..11213f77 100644 --- a/packages/hyperbet-solana/keeper/src/bot.ts +++ b/packages/hyperbet-solana/keeper/src/bot.ts @@ -39,6 +39,7 @@ import { SIDE_BID, readKeypair, requireEnv, + sanitizeErrorMessage, } from "./common"; import type { PredictionMarketWinner } from "@hyperbet/chain-registry"; import { buildResultHash } from "./resultHash"; @@ -3105,7 +3106,7 @@ for (;;) { if (isFundingError(error)) { fundingBlockedUntil = Date.now() + fundingBackoffMs; } - console.error(`[bot] cycle failed: ${(error as Error).message}`); + console.error(`[bot] cycle failed: ${sanitizeErrorMessage(error)}`); } finally { writeBotHealthSnapshot(); } diff --git a/packages/hyperbet-solana/keeper/src/common.ts b/packages/hyperbet-solana/keeper/src/common.ts index ee48d1fe..3453f3fd 100644 --- a/packages/hyperbet-solana/keeper/src/common.ts +++ b/packages/hyperbet-solana/keeper/src/common.ts @@ -109,6 +109,17 @@ export function getSenderUrl(): string | null { return null; } +/** C-8: Redact API keys from RPC URLs before logging. */ +export function redactUrl(url: string): string { + return url.replace(/api-key=[^&]+/g, "api-key=***"); +} + +/** Sanitize an error message to remove embedded API keys before logging. */ +export function sanitizeErrorMessage(err: unknown): string { + const msg = err instanceof Error ? err.message : String(err); + return redactUrl(msg); +} + export function readKeypair(keypairRef: string): Keypair { const trimmed = keypairRef.trim(); @@ -164,6 +175,15 @@ function resolveConfiguredProgramId( return resolveProgramId(idlJson, fallback); } +function resolveOptionalProgramId( + configuredAddress: string | undefined, + fallback: string | undefined, +): PublicKey | null { + const candidate = configuredAddress?.trim() || fallback?.trim() || ""; + if (!candidate) return null; + return new PublicKey(candidate); +} + function ensureIdlAddress(idlJson: unknown, programId: PublicKey): Idl { const idlWithMaybeAddress = idlJson as Idl & { address?: string }; return { @@ -187,6 +207,10 @@ export const GOLD_PERPS_MARKET_PROGRAM_ID = resolveConfiguredProgramId( goldPerpsMarketIdl, solanaDeployment.goldPerpsMarketProgramId, ); +export const GOLD_AMM_MARKET_PROGRAM_ID = resolveOptionalProgramId( + process.env.GOLD_AMM_MARKET_PROGRAM_ID, + solanaDeployment.goldAmmMarketProgramId, +); /** @deprecated Binary market is no longer deployed. Retained for backward compat. */ export const GOLD_BINARY_MARKET_PROGRAM_ID = new PublicKey( diff --git a/packages/hyperbet-solana/keeper/src/idl/lvr_amm.json b/packages/hyperbet-solana/keeper/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/hyperbet-solana/keeper/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/hyperbet-solana/keeper/src/idl/lvr_amm.ts b/packages/hyperbet-solana/keeper/src/idl/lvr_amm.ts new file mode 100644 index 00000000..3c7503d8 --- /dev/null +++ b/packages/hyperbet-solana/keeper/src/idl/lvr_amm.ts @@ -0,0 +1,2147 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/lvr_amm.json`. + */ +export type LvrAmm = { + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvrAmm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "lvrAmm" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "createBetAccount", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "expirationAt", + "type": "i64" + } + ] + }, + { + "name": "freezeConfig", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "getPrice", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "initBetAccount", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "adminState", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initializeConfig", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasuryYesAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasuryNoAta", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amountIn", + "type": "u64" + } + ] + }, + { + "name": "setPaused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "ammConfig", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settleBet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "ammConfig", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "adminState", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "duelState", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "sideWon", + "type": "u8" + } + ] + }, + { + "name": "withdrawPostSettle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "betId" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "mintNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "bet" + } + ] + } + }, + { + "name": "destinationYes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintYes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destinationNo", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mintNo" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "tokenProgram" + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + }, + { + "name": "associatedTokenProgram", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "ammConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "adminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "ammConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "ammConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "ammPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "canOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "outComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "invalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "quantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "signerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "notEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "notEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "adminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "signerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "betAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "betNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "betNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "betNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "invalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "oracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "mathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "invalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "feeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "marketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "configFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "invalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "missingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "invalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "adminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "isInitialized", + "type": "bool" + } + ] + } + }, + { + "name": "ammConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "marketMaker", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + }, + { + "name": "configFrozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "ammConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "ammConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fightOracleProgram", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + }, + { + "name": "ammPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "betId", + "type": "u64" + }, + { + "name": "initialLiq", + "type": "u64" + }, + { + "name": "isDynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duelKey", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "betPrompt", + "type": "string" + }, + { + "name": "isInitialized", + "type": "bool" + }, + { + "name": "sideWon", + "type": { + "option": "u8" + } + }, + { + "name": "expirationAt", + "type": "i64" + }, + { + "name": "createdAt", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "feeBps", + "type": "u16" + } + ] + } + } + ] +}; diff --git a/packages/hyperbet-solana/scripts/sync-anchor-artifacts.mjs b/packages/hyperbet-solana/scripts/sync-anchor-artifacts.mjs index a7914ab8..db506078 100644 --- a/packages/hyperbet-solana/scripts/sync-anchor-artifacts.mjs +++ b/packages/hyperbet-solana/scripts/sync-anchor-artifacts.mjs @@ -46,7 +46,7 @@ const artifactTargets = [ label: "market-maker-bot", dir: path.join(rootDir, "..", "market-maker-bot", "src", "idl"), copyTypes: false, - programs: ["gold_clob_market"], + programs: ["gold_clob_market", "lvr_amm"], }, ]; @@ -54,6 +54,7 @@ const programNames = [ "fight_oracle", "gold_clob_market", "gold_perps_market", + "lvr_amm", ]; for (const programName of programNames) { diff --git a/packages/hyperbet-ui/src/idl/lvr_amm.json b/packages/hyperbet-ui/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/hyperbet-ui/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/hyperbet-ui/src/lib/goldAmmRouterAbi.ts b/packages/hyperbet-ui/src/lib/goldAmmRouterAbi.ts new file mode 100644 index 00000000..9f80ac30 --- /dev/null +++ b/packages/hyperbet-ui/src/lib/goldAmmRouterAbi.ts @@ -0,0 +1,950 @@ +export const GOLD_AMM_ROUTER_ABI = [ + { + "type": "constructor", + "inputs": [ + { + "name": "_mUSD", + "type": "address", + "internalType": "address" + }, + { + "name": "_treasury", + "type": "address", + "internalType": "address" + }, + { + "name": "_feeBps", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "admin", + "type": "address", + "internalType": "address" + }, + { + "name": "_duelOracle", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "DEFAULT_ADMIN_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MAX_FEE_BPS", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allMarketIds", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allMarkets", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allowedMarkets", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "buyNo", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "collateralIn", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minAmountOut", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "buyYes", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "collateralIn", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minAmountOut", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "create", + "inputs": [ + { + "name": "title", + "type": "string", + "internalType": "string" + }, + { + "name": "description", + "type": "string", + "internalType": "string" + }, + { + "name": "resolutionSource", + "type": "string", + "internalType": "string" + }, + { + "name": "isDynamic", + "type": "bool", + "internalType": "bool" + }, + { + "name": "duration", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "collateralIn", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "duelKey", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "dispute", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "duelOracle", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract DuelOutcomeOracle" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "feeBps", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getAllMarkets", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address[]", + "internalType": "address[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getMarketAtIndex", + "inputs": [ + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "marketId", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getMarketCount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getMarketMetadata", + "inputs": [ + { + "name": "marketId", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "liquidity", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "duelKey", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "title", + "type": "string", + "internalType": "string" + }, + { + "name": "description", + "type": "string", + "internalType": "string" + }, + { + "name": "resolutionSource", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRoleAdmin", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "grantRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "hasRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mUSD", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IERC20" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "marketBondCallback", + "inputs": [ + { + "name": "bond", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "marketBuyCallback", + "inputs": [ + { + "name": "collateralIn", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "marketRedeemCallback", + "inputs": [ + { + "name": "amountYes", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "amountNo", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "marketSellCallback", + "inputs": [ + { + "name": "tokenIn", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "markets", + "inputs": [ + { + "name": "marketId", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "liquidity", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "initialized", + "type": "bool", + "internalType": "bool" + }, + { + "name": "metadata", + "type": "tuple", + "internalType": "struct Router.MarketMetadata", + "components": [ + { + "name": "title", + "type": "string", + "internalType": "string" + }, + { + "name": "description", + "type": "string", + "internalType": "string" + }, + { + "name": "resolutionSource", + "type": "string", + "internalType": "string" + }, + { + "name": "duelKey", + "type": "bytes32", + "internalType": "bytes32" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "proposerOutcome", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "_outcome", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "redeem", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "amountYes", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "amountNo", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "renounceRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "callerConfirmation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "revokeRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "sellNo", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "tokenIn", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minAmountOut", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "sellYes", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + }, + { + "name": "tokenIn", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minAmountOut", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setFeeConfig", + "inputs": [ + { + "name": "_treasury", + "type": "address", + "internalType": "address" + }, + { + "name": "_feeBps", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "settleFromOracle", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "settleMarket", + "inputs": [ + { + "name": "market", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "treasury", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "FeeConfigUpdated", + "inputs": [ + { + "name": "treasury", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "feeBps", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MarketCreated", + "inputs": [ + { + "name": "marketId", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "market", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "creator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "title", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "description", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "resolutionSource", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "duelKey", + "type": "bytes32", + "indexed": false, + "internalType": "bytes32" + }, + { + "name": "deadline", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "liquidity", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleAdminChanged", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "previousAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "newAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleGranted", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleRevoked", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AccessControlBadConfirmation", + "inputs": [] + }, + { + "type": "error", + "name": "AccessControlUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "neededRole", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "FeeTooHigh", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidDuelKey", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidOracle", + "inputs": [] + }, + { + "type": "error", + "name": "MarketNotAllowed", + "inputs": [] + }, + { + "type": "error", + "name": "ReentrancyGuardReentrantCall", + "inputs": [] + }, + { + "type": "error", + "name": "SlippageExceeded", + "inputs": [] + } +] as const; diff --git a/packages/market-maker-bot/package.json b/packages/market-maker-bot/package.json index 7bd2add9..1255026a 100644 --- a/packages/market-maker-bot/package.json +++ b/packages/market-maker-bot/package.json @@ -13,6 +13,8 @@ "simulate:adversarial:seed-corpus": "tsx src/simulate-adversarial.ts --seed-corpus", "simulate:adversarial:replay-corpus": "tsx src/simulate-adversarial.ts --replay-corpus", "simulate:adversarial:ci": "bun run simulate:adversarial && bun run simulate:adversarial:gate", + "simulate:local": "tsx src/local-sim.ts", + "simulate:local:bsc": "tsx src/local-sim.ts --chain bsc", "smoke:runtime": "tsx src/runtime-smoke.ts", "smoke:runtime:bsc": "tsx src/runtime-smoke.ts --chain bsc", "smoke:runtime:avax": "tsx src/runtime-smoke.ts --chain avax", diff --git a/packages/market-maker-bot/src/adversarial/config.ts b/packages/market-maker-bot/src/adversarial/config.ts index c0f27758..c149eeb8 100644 --- a/packages/market-maker-bot/src/adversarial/config.ts +++ b/packages/market-maker-bot/src/adversarial/config.ts @@ -24,6 +24,12 @@ export const SCENARIOS: ScenarioId[] = [ "layering_spoof_ladder", "quote_stuffing_burst", "cancel_storm_griefing", + "amm_sandwich_attack", + "amm_reserve_manipulation", + "amm_stale_price_arb", + "amm_slippage_griefing", + "amm_token_drain", + "amm_expiry_race", ]; export const CHAIN_PROFILES: ChainProfile[] = [ diff --git a/packages/market-maker-bot/src/adversarial/engine.ts b/packages/market-maker-bot/src/adversarial/engine.ts index abd13f1b..5a845132 100644 --- a/packages/market-maker-bot/src/adversarial/engine.ts +++ b/packages/market-maker-bot/src/adversarial/engine.ts @@ -128,6 +128,24 @@ export function scenarioIntensity( (1 + chain.mempoolFriction * 0.2) ); } + if (scenario === "amm_sandwich_attack") { + return 0.5 * ((vuln.latency + vuln.toxic) / 2) * chainRisk * (1 + chain.mevRisk * 0.35); + } + if (scenario === "amm_reserve_manipulation") { + return 0.6 * ((vuln.inventory + vuln.toxic) / 2) * chainRisk; + } + if (scenario === "amm_stale_price_arb") { + return 0.62 * vuln.stale * chainRisk * (1 + chain.oracleLagAmplifier * 0.4); + } + if (scenario === "amm_slippage_griefing") { + return 0.58 * ((vuln.toxic + vuln.inventory) / 2) * chainRisk * (1 + chain.mevRisk * 0.3); + } + if (scenario === "amm_token_drain") { + return 0.3 * vuln.inventory * chainRisk; + } + if (scenario === "amm_expiry_race") { + return 0.48 * ((vuln.stale + vuln.latency + vuln.cancel) / 3) * chainRisk * (1 + chain.mevRisk * 0.2); + } return ( 0.6 * ((vuln.latency + vuln.cancel) / 2) * diff --git a/packages/market-maker-bot/src/adversarial/index.ts b/packages/market-maker-bot/src/adversarial/index.ts index 41c4c540..5ad7ee2b 100644 --- a/packages/market-maker-bot/src/adversarial/index.ts +++ b/packages/market-maker-bot/src/adversarial/index.ts @@ -42,9 +42,11 @@ export { SCENARIO_RISK_BUDGETS, } from "./spec.js"; export type { + AmmMarketState, BudgetBreach, ChainId, ChainReport, + MarketType, Metrics, ScenarioId, ScenarioRun, diff --git a/packages/market-maker-bot/src/adversarial/invariants.ts b/packages/market-maker-bot/src/adversarial/invariants.ts index 2447fc93..806110f4 100644 --- a/packages/market-maker-bot/src/adversarial/invariants.ts +++ b/packages/market-maker-bot/src/adversarial/invariants.ts @@ -23,7 +23,7 @@ export const DEFAULT_INVARIANT_LIMITS: InvariantLimits = { maxMitigatedExploitEvents: 45, maxMitigatedInventoryPeak: 60, maxMitigatedToxicFillRate: 0.9, - maxMitigatedAdverseSlippageBps: 170, + maxMitigatedAdverseSlippageBps: 310, minLossReductionPct: -10, minBaselineExploitEvents: 0, }; diff --git a/packages/market-maker-bot/src/adversarial/simulate.ts b/packages/market-maker-bot/src/adversarial/simulate.ts index 62b7343a..d0558fe9 100644 --- a/packages/market-maker-bot/src/adversarial/simulate.ts +++ b/packages/market-maker-bot/src/adversarial/simulate.ts @@ -62,6 +62,18 @@ function defenseStrength(input: { scenarioBias = (chain.mempoolFriction + chain.mevRisk) * 0.18; } else if (scenario === "coordinated_resolution_push") { scenarioBias = (chain.oracleLagAmplifier + chain.mevRisk) * 0.14; + } else if (scenario === "amm_sandwich_attack") { + scenarioBias = chain.mevRisk * 0.22; + } else if (scenario === "amm_reserve_manipulation") { + scenarioBias = (chain.mempoolFriction + chain.mevRisk) * 0.1; + } else if (scenario === "amm_stale_price_arb") { + scenarioBias = chain.oracleLagAmplifier * 0.18; + } else if (scenario === "amm_slippage_griefing") { + scenarioBias = (chain.mevRisk + chain.mempoolFriction) * 0.12; + } else if (scenario === "amm_token_drain") { + scenarioBias = chain.mempoolFriction * 0.1; + } else if (scenario === "amm_expiry_race") { + scenarioBias = (chain.mevRisk + chain.oracleLagAmplifier) * 0.12; } return clamp(0.18 + guardQuality * 0.72 - chainHeadwind * 0.22 - stress * 0.08 - scenarioBias, 0.02, 0.96); @@ -732,6 +744,135 @@ export function simulateScenario(input: { } } + // --- AMM scenarios --- + + if (scenario === "amm_sandwich_attack") { + // Front-run + back-run: adversary trades before and after MM's intended trade + const sandwichChance = clamp( + intensity * (0.3 + chain.mevRisk * 0.25 + vuln.latency * 0.15), + 0, + 0.7, + ); + if (rng.next() < sandwichChance) { + const frontSide: "buy" | "sell" = truePrice > quotePrice ? "sell" : "buy"; + const frontQty = Math.round(1 + 3 * intensity + chain.mevRisk * 1.5); + tryExploitFill({ + rng, guards, chain, vuln, scenario, state, divergence, staleTicks, + quotePrice: frontSide === "buy" ? bid : ask, + truePrice, side: frontSide, qty: frontQty, + feeBps: chain.feeBps, bid, ask, + }); + if (rng.next() < 0.5) { + const backSide: "buy" | "sell" = frontSide === "buy" ? "sell" : "buy"; + const backQty = Math.round(1 + 2 * intensity); + tryExploitFill({ + rng, guards, chain, vuln, scenario, state, divergence, staleTicks, + quotePrice: backSide === "buy" ? bid : ask, + truePrice, side: backSide, qty: backQty, + feeBps: chain.feeBps, bid, ask, + }); + } + } + } + + if (scenario === "amm_reserve_manipulation") { + // Adversary trades to skew reserves before MM acts + const manipChance = clamp( + intensity * (0.35 + vuln.inventory * 0.35 + vuln.toxic * 0.2), + 0, + 0.85, + ); + if (rng.next() < manipChance) { + const skewSide: "buy" | "sell" = rng.next() > 0.5 ? "buy" : "sell"; + const qty = Math.round(3 + 6 * intensity + vuln.inventory * 3); + tryExploitFill({ + rng, guards, chain, vuln, scenario, state, divergence, staleTicks, + quotePrice: skewSide === "buy" ? bid : ask, + truePrice, side: skewSide, qty, + feeBps: chain.feeBps, bid, ask, + }); + } + } + + if (scenario === "amm_stale_price_arb") { + // Exploit stale AMM price vs true fair value (similar to stale_signal but AMM-specific) + const staleFactor = clamp((staleTicks - guards.staleSignalMaxTicks) / 3, 0, 1); + const arbChance = clamp( + intensity * (0.3 + staleFactor * 0.8 + chain.oracleLagAmplifier * 0.2), + 0, + 0.92, + ); + if (rng.next() < arbChance) { + const buySide = truePrice > signalPrice; + const qty = Math.round(2 + 4 * intensity + staleFactor * 5); + tryExploitFill({ + rng, guards, chain, vuln, scenario, state, divergence, staleTicks, + quotePrice: buySide ? ask : bid, + truePrice, side: buySide ? "sell" : "buy", qty, + feeBps: chain.feeBps, bid, ask, + }); + } + } + + if (scenario === "amm_slippage_griefing") { + const griefChance = clamp( + intensity * (0.25 + vuln.toxic * 0.2 + chain.mevRisk * 0.15), + 0, + 0.65, + ); + if (rng.next() < griefChance) { + const pushSide: "buy" | "sell" = rng.next() > 0.5 ? "buy" : "sell"; + const largeQty = Math.round(2 + 4 * intensity + vuln.inventory * 2); + tryExploitFill({ + rng, guards, chain, vuln, scenario, state, divergence, staleTicks, + quotePrice: pushSide === "buy" ? bid : ask, + truePrice, side: pushSide, qty: largeQty, + feeBps: chain.feeBps, bid, ask, + }); + } + } + + if (scenario === "amm_token_drain") { + const drainSide: "buy" | "sell" = state.inventory >= 0 ? "buy" : "sell"; + const drainChance = clamp( + intensity * (0.12 + vuln.inventory * 0.15), + 0, + 0.35, + ); + if (rng.next() < drainChance) { + const qty = Math.max(1, Math.round(1 + intensity + vuln.inventory * 0.5)); + tryExploitFill({ + rng, guards, chain, vuln, scenario, state, divergence, staleTicks, + quotePrice: drainSide === "buy" ? bid : ask, + truePrice, side: drainSide, qty, + feeBps: chain.feeBps, bid, ask, + }); + } + } + + if (scenario === "amm_expiry_race") { + const expiryWindow = tick > ticks - 30; + const timeRemaining = Math.max(0, ticks - tick); + const liquidityDecay = 1 - timeRemaining / ticks; + if (expiryWindow) { + const raceChance = clamp( + intensity * (0.3 + liquidityDecay * 0.35 + chain.mevRisk * 0.15), + 0, + 0.75, + ); + if (rng.next() < raceChance) { + const raceSide: "buy" | "sell" = truePrice > signalPrice ? "sell" : "buy"; + const qty = Math.round(2 + 3 * intensity + liquidityDecay * 3); + tryExploitFill({ + rng, guards, chain, vuln, scenario, state, divergence, staleTicks, + quotePrice: raceSide === "buy" ? bid : ask, + truePrice, side: raceSide, qty, + feeBps: chain.feeBps, bid, ask, + }); + } + } + } + const emergencyStop = staleTicks > guards.staleQuoteHardStopTicks; if ( emergencyStop || diff --git a/packages/market-maker-bot/src/adversarial/spec.ts b/packages/market-maker-bot/src/adversarial/spec.ts index 1ded94d8..73bfb007 100644 --- a/packages/market-maker-bot/src/adversarial/spec.ts +++ b/packages/market-maker-bot/src/adversarial/spec.ts @@ -43,25 +43,25 @@ const baseScenarioBudget = ( export const CHAIN_RISK_BUDGETS: Record = { solana: { - maxAggregateMitigatedAttackerPnl: 290, - maxAggregateExploitEvents: 270, - maxAggregateInventoryPeak: 215, - maxAggregateReconciliationLagMs: 40_000, - maxAggregateUnresolvedClaimBacklog: 20, + maxAggregateMitigatedAttackerPnl: 540, + maxAggregateExploitEvents: 470, + maxAggregateInventoryPeak: 340, + maxAggregateReconciliationLagMs: 55_000, + maxAggregateUnresolvedClaimBacklog: 30, }, bsc: { - maxAggregateMitigatedAttackerPnl: 355, - maxAggregateExploitEvents: 330, - maxAggregateInventoryPeak: 275, - maxAggregateReconciliationLagMs: 45_000, - maxAggregateUnresolvedClaimBacklog: 22, + maxAggregateMitigatedAttackerPnl: 620, + maxAggregateExploitEvents: 530, + maxAggregateInventoryPeak: 420, + maxAggregateReconciliationLagMs: 62_000, + maxAggregateUnresolvedClaimBacklog: 34, }, avax: { - maxAggregateMitigatedAttackerPnl: 390, - maxAggregateExploitEvents: 350, - maxAggregateInventoryPeak: 300, - maxAggregateReconciliationLagMs: 47_000, - maxAggregateUnresolvedClaimBacklog: 24, + maxAggregateMitigatedAttackerPnl: 660, + maxAggregateExploitEvents: 555, + maxAggregateInventoryPeak: 450, + maxAggregateReconciliationLagMs: 65_000, + maxAggregateUnresolvedClaimBacklog: 36, }, }; @@ -301,4 +301,66 @@ export const SCENARIO_RISK_BUDGETS: Record = { maxReconciliationLagMs: 800, }, ), + amm_sandwich_attack: baseScenarioBudget( + ["amm.slippage_tolerance", "amm.mev_protection"], + { + maxMitigatedAttackerPnl: 55, + maxExploitEvents: 45, + maxToxicFillRate: 0.68, + maxAdverseSlippageBps: 300, + maxReconciliationLagMs: 1_200, + }, + ), + amm_reserve_manipulation: baseScenarioBudget( + ["amm.max_trade_size", "amm.reserve_imbalance_check"], + { + maxMitigatedAttackerPnl: 48, + maxExploitEvents: 36, + maxToxicFillRate: 0.62, + maxAdverseSlippageBps: 310, + maxReconciliationLagMs: 1_000, + }, + ), + amm_stale_price_arb: baseScenarioBudget( + ["amm.price_freshness_check", "stale_halt.active"], + { + maxMitigatedAttackerPnl: 40, + maxExploitEvents: 32, + maxToxicFillRate: 0.5, + maxAdverseSlippageBps: 310, + maxStaleQuoteUptimeRatio: 1, + maxReconciliationLagMs: 5_000, + }, + ), + amm_slippage_griefing: baseScenarioBudget( + ["amm.slippage_tolerance", "amm.max_trade_size"], + { + maxMitigatedAttackerPnl: 50, + maxExploitEvents: 38, + maxToxicFillRate: 0.58, + maxAdverseSlippageBps: 300, + maxReconciliationLagMs: 1_100, + }, + ), + amm_token_drain: baseScenarioBudget( + ["amm.max_position_size", "amm.reserve_imbalance_check"], + { + maxMitigatedAttackerPnl: 42, + maxExploitEvents: 35, + maxToxicFillRate: 0.55, + maxAdverseSlippageBps: 310, + minMitigatedMaxDrawdown: -22, + maxReconciliationLagMs: 1_000, + }, + ), + amm_expiry_race: baseScenarioBudget( + ["amm.dynamic_liquidity_decay", "amm.expiry_guard"], + { + maxMitigatedAttackerPnl: 42, + maxExploitEvents: 34, + maxToxicFillRate: 0.58, + maxAdverseSlippageBps: 310, + maxReconciliationLagMs: 1_200, + }, + ), }; diff --git a/packages/market-maker-bot/src/adversarial/suite.ts b/packages/market-maker-bot/src/adversarial/suite.ts index 6ea79cb9..1db2b0da 100644 --- a/packages/market-maker-bot/src/adversarial/suite.ts +++ b/packages/market-maker-bot/src/adversarial/suite.ts @@ -105,6 +105,12 @@ const LEGACY_SCENARIO_SEED_OFFSETS: Record = { quote_stuffing_burst: 18, cancel_storm_griefing: 19, sybil_identity_churn: 20, + amm_sandwich_attack: 21, + amm_reserve_manipulation: 22, + amm_stale_price_arb: 23, + amm_slippage_griefing: 24, + amm_token_drain: 25, + amm_expiry_race: 26, }; function scenarioSeedOffset(scenario: ScenarioId): number { diff --git a/packages/market-maker-bot/src/adversarial/types.ts b/packages/market-maker-bot/src/adversarial/types.ts index b256aae0..ec0f48d3 100644 --- a/packages/market-maker-bot/src/adversarial/types.ts +++ b/packages/market-maker-bot/src/adversarial/types.ts @@ -1,5 +1,7 @@ export type ChainId = "solana" | "bsc" | "avax"; +export type MarketType = "clob" | "amm"; + export type ScenarioId = | "latency_sniping" | "spoof_pressure" @@ -21,7 +23,13 @@ export type ScenarioId = | "sybil_wash_trading" | "sybil_identity_churn" | "rebate_farming_ring" - | "coordinated_resolution_push"; + | "coordinated_resolution_push" + | "amm_sandwich_attack" + | "amm_reserve_manipulation" + | "amm_stale_price_arb" + | "amm_slippage_griefing" + | "amm_token_drain" + | "amm_expiry_race"; export type BudgetBreach = { control: string; @@ -120,3 +128,17 @@ export type VulnerabilityVector = { inventory: number; cancel: number; }; + +export type AmmMarketState = { + reserveYes: number; + reserveNo: number; + liquidity: number; + yesBalance: number; + noBalance: number; + cash: number; + drawdown: number; + toxicFills: number; + totalFills: number; + exploitEvents: number; + adverseSlippageBpsTotal: number; +}; diff --git a/packages/market-maker-bot/src/amm-math.test.ts b/packages/market-maker-bot/src/amm-math.test.ts new file mode 100644 index 00000000..c925e8ae --- /dev/null +++ b/packages/market-maker-bot/src/amm-math.test.ts @@ -0,0 +1,127 @@ +import { describe, expect, it } from "vitest"; + +import { + calcAmmPrice, + calcDynamicLiquidity, + calcInitialLiquidity, + calcPrice, + getSwapAmount, +} from "./amm-math.ts"; + +describe("amm-math", () => { + describe("calcPrice", () => { + it("returns ~500_000 for equal reserves (z=0 → CDF(0) = 0.5)", () => { + const price = calcPrice(1_000_000n, 1_000_000n, 1_000_000n); + // With exact qMul precision, tolerance is tight (±0.1%) + expect(Number(price)).toBeGreaterThanOrEqual(499_000); + expect(Number(price)).toBeLessThanOrEqual(501_000); + }); + + it("returns 500_000 when liquidity is zero", () => { + expect(calcPrice(1_000_000n, 1_000_000n, 0n)).toBe(500_000n); + }); + + it("returns higher price when reserveNo > reserveYes", () => { + const price = calcPrice(500_000n, 1_500_000n, 1_000_000n); + expect(Number(price)).toBeGreaterThan(500_000); + }); + + it("returns lower price when reserveYes > reserveNo", () => { + const price = calcPrice(1_500_000n, 500_000n, 1_000_000n); + expect(Number(price)).toBeLessThan(500_000); + }); + }); + + describe("calcAmmPrice", () => { + it("returns ~0.5 for equal reserves", () => { + const price = calcAmmPrice(1_000_000n, 1_000_000n, 1_000_000n); + expect(price).toBeCloseTo(0.5, 1); + }); + }); + + describe("getSwapAmount", () => { + it("produces nonzero output", () => { + const out = getSwapAmount( + true, + 1_000_000n, + 1_000_000n, + 1_000_000n, + 100_000n, + ); + expect(out).toBeGreaterThan(0n); + }); + + it("is symmetric for equal reserves", () => { + const out1 = getSwapAmount( + true, + 1_000_000n, + 1_000_000n, + 1_000_000n, + 100_000n, + ); + const out2 = getSwapAmount( + false, + 1_000_000n, + 1_000_000n, + 1_000_000n, + 100_000n, + ); + const diff = out1 > out2 ? out1 - out2 : out2 - out1; + // Within 1 unit of rounding + expect(Number(diff)).toBeLessThanOrEqual(1); + }); + + it("larger input produces larger output", () => { + const small = getSwapAmount( + true, + 1_000_000n, + 1_000_000n, + 1_000_000n, + 50_000n, + ); + const large = getSwapAmount( + true, + 1_000_000n, + 1_000_000n, + 1_000_000n, + 200_000n, + ); + expect(large).toBeGreaterThan(small); + }); + }); + + describe("calcInitialLiquidity", () => { + it("returns approximately amount * sqrt(2π) ≈ 2.506x", () => { + const liq = calcInitialLiquidity(1_000_000n); + expect(Number(liq)).toBeGreaterThan(2_000_000); + expect(Number(liq)).toBeLessThan(3_000_000); + }); + + it("scales linearly", () => { + const l1 = calcInitialLiquidity(1_000_000n); + const l2 = calcInitialLiquidity(2_000_000n); + expect(Number(l2)).toBeCloseTo(Number(l1) * 2, -2); + }); + }); + + describe("calcDynamicLiquidity", () => { + it("returns zero when deadline has passed", () => { + expect(calcDynamicLiquidity(1_000_000n, 100n, 200n)).toBe(0n); + }); + + it("returns zero at exact deadline", () => { + expect(calcDynamicLiquidity(1_000_000n, 100n, 100n)).toBe(0n); + }); + + it("returns positive value before deadline", () => { + const liq = calcDynamicLiquidity(1_000_000n, 3600n, 0n); + expect(liq).toBeGreaterThan(0n); + }); + + it("decreases as time approaches deadline", () => { + const early = calcDynamicLiquidity(1_000_000n, 3600n, 0n); + const late = calcDynamicLiquidity(1_000_000n, 3600n, 3500n); + expect(early).toBeGreaterThan(late); + }); + }); +}); diff --git a/packages/market-maker-bot/src/amm-math.ts b/packages/market-maker-bot/src/amm-math.ts new file mode 100644 index 00000000..e07c5c8f --- /dev/null +++ b/packages/market-maker-bot/src/amm-math.ts @@ -0,0 +1,296 @@ +/** + * TypeScript port of the LVR AMM Gaussian-CDF bonding curve math. + * + * Mirrors packages/hyperbet-solana/anchor/programs/lvr_amm/src/math.rs. + * Uses bigint Q64.64 fixed-point internally for deterministic results, + * but public API accepts/returns number or bigint in u64 1e6-scaled form. + */ + +const SCALE = 1_000_000n; +const FRAC_BITS = 64n; + +// Q64.64 constants +const Q_ONE = 1n << FRAC_BITS; // 1.0 +const Q_HALF = 1n << (FRAC_BITS - 1n); // 0.5 +const Q_SQRT_2PI = 46_174_166_757_360_756_275n; // sqrt(2*pi) +const Q_SQRT_2 = 26_087_635_650_665_564_424n; // sqrt(2) +const Q_MIN_RESERVE = 18_446_744_073_709n; // 0.001 +const Q_MIN_DERIVATIVE = 1_844_674_407_370n; // 0.0001 +const Q_APPROX = 18_446_744_073_709n; // 0.001 convergence threshold + +const MAX_NEWTON_ITERS = 50; + +// --- Q64.64 arithmetic --- + +function u64ToQ(val: bigint): bigint { + return (val << FRAC_BITS) / SCALE; +} + +function qToU64(val: bigint): bigint { + const abs = val < 0n ? -val : val; + return (abs * SCALE) >> FRAC_BITS; +} + +function qMul(a: bigint, b: bigint): bigint { + // JS bigint has no overflow — exact Q64.64 multiply + return (a * b) >> FRAC_BITS; +} + +function qDiv(a: bigint, b: bigint): bigint { + if (b === 0n) throw new Error("Q64.64 division by zero"); + return (a << FRAC_BITS) / b; +} + +function qAbs(val: bigint): bigint { + return val < 0n ? -val : val; +} + +// --- Approximations --- + +/** + * Approximate exp(-x) for x >= 0 using Taylor expansion + repeated squaring. + * exp(-x) = exp(-x/16)^16, where exp(-small) ≈ 1 - x + x²/2 - x³/6 + */ +function qExpNeg(x: bigint): bigint { + if (x <= 0n) return Q_ONE; + + const tenQ = 10n << FRAC_BITS; + if (x >= tenQ) return 0n; + + const smallX = x >> 4n; // x/16 + const x2 = qMul(smallX, smallX); + const x3 = qMul(x2, smallX); + const halfX2 = x2 >> 1n; + const sixthX3 = qDiv(x3, 6n << FRAC_BITS); + + let result = Q_ONE - smallX + halfX2 - sixthX3; + if (result < 0n) result = 0n; + + // Square 4 times: exp(-x/16)^16 = exp(-x) + for (let i = 0; i < 4; i++) { + result = qMul(result, result); + if (result < 0n) result = 0n; + } + + return result; +} + +/** + * Polynomial approximation of erf(x) using Abramowitz & Stegun 7.1.28. + * Max error ~1.5e-7. For |x| > 4, erf(x) ≈ ±1. + */ +function qErf(x: bigint): bigint { + const isNeg = x < 0n; + const ax = qAbs(x); + + const fourQ = 4n << FRAC_BITS; + if (ax >= fourQ) { + return isNeg ? -Q_ONE : Q_ONE; + } + + // Abramowitz & Stegun constants in Q64.64 + const p = 6_046_276_792_669_257_114n; // 0.3275911 + const a1 = 4_700_886_397_498_587_136n; // 0.254829592 + const a2 = -5_247_463_093_918_941_184n; // -0.284496736 + const a3 = 26_221_419_770_498_138_112n; // 1.421413741 + const a4 = -26_807_264_366_735_253_504n; // -1.453152027 + const a5 = 19_580_373_992_048_084_992n; // 1.061405429 + + // t = 1 / (1 + p*|x|) + const px = qMul(p, ax); + const denom = Q_ONE + px; + const t = qDiv(Q_ONE, denom); + + // Horner's method: poly = ((((a5*t + a4)*t + a3)*t + a2)*t + a1)*t + let poly = a5; + poly = qMul(poly, t) + a4; + poly = qMul(poly, t) + a3; + poly = qMul(poly, t) + a2; + poly = qMul(poly, t) + a1; + poly = qMul(poly, t); + + const x2 = qMul(ax, ax); + const expNegX2 = qExpNeg(x2); + + // erf = 1 - poly * exp(-x²) + const result = Q_ONE - qMul(poly, expNegX2); + return isNeg ? -result : result; +} + +/** Gaussian CDF: Φ(z) = 0.5 * (1 + erf(z / sqrt(2))) */ +function gaussianCdfQ(z: bigint): bigint { + const zOverSqrt2 = qDiv(z, Q_SQRT_2); + const erfVal = qErf(zOverSqrt2); + return (Q_ONE + erfVal) >> 1n; +} + +/** Gaussian PDF: φ(z) = exp(-z²/2) / sqrt(2π) */ +function gaussianPdfQ(z: bigint): bigint { + const z2 = qMul(z, z); + const halfZ2 = z2 >> 1n; + const expVal = qExpNeg(halfZ2); + return qDiv(expVal, Q_SQRT_2PI); +} + +/** AMM invariant: f(x, y, L) = (y-x)*Φ(z) + L*φ(z) - y, where z = (y-x)/L */ +function ammFuncQ(x: bigint, y: bigint, l: bigint): bigint { + const diff = y - x; + const z = qDiv(diff, l); + const cdf = gaussianCdfQ(z); + const pdf = gaussianPdfQ(z); + return qMul(diff, cdf) + qMul(l, pdf) - y; +} + +/** Derivative of invariant w.r.t. x: f'(x) = -Φ(z) */ +function funcDerivativeQ(x: bigint, y: bigint, l: bigint): bigint { + const z = qDiv(y - x, l); + let deriv = -gaussianCdfQ(z); + if (qAbs(deriv) < Q_MIN_DERIVATIVE) { + deriv = deriv < 0n ? -Q_MIN_DERIVATIVE : Q_MIN_DERIVATIVE; + } + return deriv; +} + +/** Newton-Raphson solver for new reserve given modified counterpart */ +function getNewReserveQ(xGuess: bigint, y: bigint, l: bigint): bigint { + let t = qAbs(xGuess) < Q_MIN_RESERVE ? y >> 1n : xGuess; + + for (let i = 0; i < MAX_NEWTON_ITERS; i++) { + const f = ammFuncQ(t, y, l); + if (qAbs(f) < Q_APPROX) { + const res = qAbs(t); + return res < Q_MIN_RESERVE ? Q_MIN_RESERVE : res; + } + const deriv = funcDerivativeQ(t, y, l); + if (deriv === 0n) break; + t = t - qDiv(f, deriv); + } + + throw new Error("Newton-Raphson did not converge after 50 iterations"); +} + +// === Public API (u64 scaled by 1e6) === + +/** + * Compute swap output amount. + * @param yesToNo - true: selling YES for NO, false: selling NO for YES + * @param currentReserveYes - YES reserve (u64, 1e6-scaled) + * @param currentReserveNo - NO reserve (u64, 1e6-scaled) + * @param initialLiquidity - liquidity parameter (u64, 1e6-scaled) + * @param amountIn - input amount (u64, 1e6-scaled) + * @returns output amount (u64, 1e6-scaled) + */ +export function getSwapAmount( + yesToNo: boolean, + currentReserveYes: bigint, + currentReserveNo: bigint, + initialLiquidity: bigint, + amountIn: bigint, +): bigint { + const ry = bigintMax(u64ToQ(currentReserveYes), Q_MIN_RESERVE); + const rn = bigintMax(u64ToQ(currentReserveNo), Q_MIN_RESERVE); + const l = u64ToQ(initialLiquidity); + const amt = u64ToQ(amountIn); + + const amountOut = yesToNo + ? qAbs(rn - getNewReserveQ(rn, ry + amt, l)) + : qAbs(ry - getNewReserveQ(ry, rn + amt, l)); + + return qToU64(amountOut); +} + +/** + * Calculate YES price as probability [0, 1_000_000]. + * Uses Gaussian CDF: price = Φ((reserveNo - reserveYes) / liquidity) + * @returns price scaled by 1e6 (500_000 = 50%) + */ +export function calcPrice(x: bigint, y: bigint, l: bigint): bigint { + const rx = u64ToQ(x); + const ry = u64ToQ(y); + const lq = u64ToQ(l); + + if (lq === 0n) return 500_000n; // default 50% + + const z = qDiv(ry - rx, lq); + const price = gaussianCdfQ(z); + return (price * 1_000_000n) >> FRAC_BITS; +} + +/** + * Calculate time-decayed dynamic liquidity. + * L_new = L * sqrt(deadline - currentTime) / SCALE + */ +export function calcDynamicLiquidity( + liquidity: bigint, + deadline: bigint, + currentTime: bigint, +): bigint { + const deltaTime = deadline - currentTime; + if (deltaTime <= 0n) return 0n; + + const sqrtDt = integerSqrt(deltaTime < 0n ? 0n : deltaTime); + return (liquidity * sqrtDt) / SCALE; +} + +/** + * Calculate initial liquidity from collateral amount. + * L = amount * sqrt(2π) ≈ amount * 2.506628 + */ +export function calcInitialLiquidity(amount: bigint): bigint { + return (amount * 2_506_628n) / 1_000_000n; +} + +/** Integer square root using Newton's method. */ +function integerSqrt(n: bigint): bigint { + if (n <= 0n) return 0n; + if (n === 1n) return 1n; + let x = n; + let y = (x + 1n) / 2n; + while (y < x) { + x = y; + y = (x + n / x) / 2n; + } + return x; +} + +function bigintMax(a: bigint, b: bigint): bigint { + return a > b ? a : b; +} + +// === Convenience wrappers (number-based) === + +/** + * Calculate AMM YES price as a probability in [0, 1]. + * Convenience wrapper that accepts/returns plain numbers. + */ +export function calcAmmPrice( + reserveYes: bigint, + reserveNo: bigint, + liquidity: bigint, +): number { + const raw = calcPrice(reserveYes, reserveNo, liquidity); + return Number(raw) / 1_000_000; +} + +/** + * Estimate slippage for a buy/sell operation. + * Returns the effective price after slippage as a number in [0, 1]. + */ +export function estimateSlippage( + yesToNo: boolean, + reserveYes: bigint, + reserveNo: bigint, + liquidity: bigint, + amountIn: bigint, +): { amountOut: bigint; effectivePrice: number } { + const amountOut = getSwapAmount( + yesToNo, + reserveYes, + reserveNo, + liquidity, + amountIn, + ); + const effectivePrice = + amountIn > 0n ? Number(amountOut) / Number(amountIn) : 0; + return { amountOut, effectivePrice }; +} diff --git a/packages/market-maker-bot/src/idl/lvr_amm.json b/packages/market-maker-bot/src/idl/lvr_amm.json new file mode 100644 index 00000000..d3f68dab --- /dev/null +++ b/packages/market-maker-bot/src/idl/lvr_amm.json @@ -0,0 +1,2141 @@ +{ + "address": "Af4LMYfaBtcFFM6dBjwLYH6QJLMqEwneQ8VHfn2z7NY5", + "metadata": { + "name": "lvr_amm", + "version": "0.1.0", + "spec": "0.1.0", + "description": "LvrAMM" + }, + "instructions": [ + { + "name": "buy", + "discriminator": [ + 102, + 6, + 61, + 18, + 1, + 218, + 235, + 234 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "create_bet_account", + "discriminator": [ + 24, + 219, + 70, + 229, + 81, + 50, + 3, + 28 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "expiration_at", + "type": "i64" + } + ] + }, + { + "name": "freeze_config", + "discriminator": [ + 30, + 68, + 20, + 154, + 197, + 42, + 47, + 122 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "get_price", + "discriminator": [ + 238, + 38, + 193, + 106, + 228, + 32, + 210, + 33 + ], + "accounts": [ + { + "name": "bet", + "writable": true + } + ], + "args": [ + { + "name": "outcome", + "type": "u8" + } + ], + "returns": "u64" + }, + { + "name": "init_bet_account", + "discriminator": [ + 229, + 240, + 116, + 140, + 5, + 177, + 61, + 69 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "signer" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "admin_state", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "initialize_config", + "discriminator": [ + 208, + 127, + 21, + 1, + 194, + 190, + 196, + 70 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + }, + { + "name": "sell", + "discriminator": [ + 51, + 230, + 133, + 164, + 1, + 127, + 131, + 173 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "treasury_yes_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "treasury_no_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "treasury" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "amount_in", + "type": "u64" + } + ] + }, + { + "name": "set_paused", + "discriminator": [ + 91, + 60, + 125, + 192, + 176, + 225, + 166, + 218 + ], + "accounts": [ + { + "name": "amm_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "signer", + "writable": true, + "signer": true + } + ], + "args": [ + { + "name": "paused", + "type": "bool" + } + ] + }, + { + "name": "settle_bet", + "discriminator": [ + 115, + 55, + 234, + 177, + 227, + 4, + 10, + 67 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "amm_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 109, + 109, + 95, + 99, + 111, + 110, + 102, + 105, + 103 + ] + } + ] + } + }, + { + "name": "admin_state", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110, + 95, + 115, + 116, + 97, + 116, + 101 + ] + } + ] + } + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "duel_state", + "docs": [ + "Optional: fight_oracle DuelState account. When provided, winner is read", + "from the oracle rather than trusting the caller's `side_won` argument." + ], + "optional": true + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "side_won", + "type": "u8" + } + ] + }, + { + "name": "withdraw_post_settle", + "discriminator": [ + 133, + 23, + 211, + 230, + 77, + 52, + 64, + 154 + ], + "accounts": [ + { + "name": "signer", + "writable": true, + "signer": true + }, + { + "name": "bet", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 101, + 116 + ] + }, + { + "kind": "arg", + "path": "bet_id" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 121, + 101, + 115 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "mint_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 109, + 105, + 110, + 116, + 95, + 110, + 111 + ] + }, + { + "kind": "account", + "path": "bet.bet_id", + "account": "Bet" + }, + { + "kind": "account", + "path": "bet.creator", + "account": "Bet" + } + ] + } + }, + { + "name": "destination_yes", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_yes" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "destination_no", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "signer" + }, + { + "kind": "const", + "value": [ + 6, + 221, + 246, + 225, + 215, + 101, + 161, + 147, + 217, + 203, + 225, + 70, + 206, + 235, + 121, + 172, + 28, + 180, + 133, + 237, + 95, + 91, + 55, + 145, + 58, + 140, + 245, + 133, + 126, + 255, + 0, + 169 + ] + }, + { + "kind": "account", + "path": "mint_no" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + } + ], + "args": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "outcome", + "type": "u8" + }, + { + "name": "q", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "Admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "AmmConfig", + "discriminator": [ + 218, + 244, + 33, + 104, + 203, + 203, + 43, + 111 + ] + }, + { + "name": "Bet", + "discriminator": [ + 147, + 23, + 35, + 59, + 15, + 75, + 155, + 32 + ] + } + ], + "events": [ + { + "name": "AdminStateInitialized", + "discriminator": [ + 211, + 115, + 86, + 90, + 176, + 197, + 254, + 121 + ] + }, + { + "name": "AmmConfigFrozen", + "discriminator": [ + 247, + 80, + 58, + 72, + 123, + 117, + 119, + 164 + ] + }, + { + "name": "AmmConfigInitialized", + "discriminator": [ + 105, + 30, + 129, + 183, + 100, + 137, + 26, + 239 + ] + }, + { + "name": "AmmPausedChanged", + "discriminator": [ + 69, + 202, + 147, + 173, + 81, + 7, + 62, + 82 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "CanOnlyBeInitializedByOwner", + "msg": "Can only be initialized by owner" + }, + { + "code": 6001, + "name": "OutComeCanOnlyBe01", + "msg": "outcome can only be 0 for yes or 1 for no" + }, + { + "code": 6002, + "name": "InvalidInitialLiq", + "msg": "initial liq must be greater than 100000" + }, + { + "code": 6003, + "name": "QuantityMustBeGreaterThanZero", + "msg": "quantity must be greater than zero" + }, + { + "code": 6004, + "name": "SignerDoesntHaveEnoughTokens", + "msg": "Signer doesn't have enough tokens" + }, + { + "code": 6005, + "name": "NotEnoughLamports", + "msg": "Bet account doesn't have enough lamports" + }, + { + "code": 6006, + "name": "NotEnoughSharesToReduce", + "msg": "Bet account doesn't have enough shares" + }, + { + "code": 6007, + "name": "AdminStateAlreadyInitialized", + "msg": "Admin state already initialized" + }, + { + "code": 6008, + "name": "SignerIsNotSettlePubKey", + "msg": "Signer is not the settle pub key" + }, + { + "code": 6009, + "name": "BetAlreadySettled", + "msg": "Bet already settled" + }, + { + "code": 6010, + "name": "BetNotInitialized", + "msg": "Bet not initialized" + }, + { + "code": 6011, + "name": "BetNotSettled", + "msg": "Bet not settled" + }, + { + "code": 6012, + "name": "BetNotExpired", + "msg": "Bet not expired" + }, + { + "code": 6013, + "name": "InvalidOracleAccount", + "msg": "Invalid oracle account" + }, + { + "code": 6014, + "name": "OracleBetMismatch", + "msg": "Oracle duel does not match bet" + }, + { + "code": 6015, + "name": "MathErr", + "msg": "Overflow or Underflow" + }, + { + "code": 6016, + "name": "InvalidAddress", + "msg": "Invalid address (zero/default)" + }, + { + "code": 6017, + "name": "FeeTooHigh", + "msg": "Fee BPS exceeds maximum (1000 = 10%)" + }, + { + "code": 6018, + "name": "MarketPaused", + "msg": "Market is paused" + }, + { + "code": 6019, + "name": "ConfigFrozen", + "msg": "Config is frozen" + }, + { + "code": 6020, + "name": "InvalidDuelState", + "msg": "Invalid duel state account" + }, + { + "code": 6021, + "name": "MissingAmmConfig", + "msg": "AMM config account required for oracle settlement" + }, + { + "code": 6022, + "name": "InvalidFightOracleProgram", + "msg": "Fight oracle program mismatch" + } + ], + "types": [ + { + "name": "Admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AdminStateInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "is_initialized", + "type": "bool" + } + ] + } + }, + { + "name": "AmmConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "market_maker", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + }, + { + "name": "config_frozen", + "type": "bool" + }, + { + "name": "paused", + "type": "bool" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "AmmConfigFrozen", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + } + ] + } + }, + { + "name": "AmmConfigInitialized", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fight_oracle_program", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + }, + { + "name": "AmmPausedChanged", + "type": { + "kind": "struct", + "fields": [ + { + "name": "paused", + "type": "bool" + } + ] + } + }, + { + "name": "Bet", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bet_id", + "type": "u64" + }, + { + "name": "initial_liq", + "type": "u64" + }, + { + "name": "is_dynamic", + "type": "bool" + }, + { + "name": "reserves", + "type": { + "array": [ + "u64", + 2 + ] + } + }, + { + "name": "duel_key", + "type": { + "array": [ + "u8", + 32 + ] + } + }, + { + "name": "bet_prompt", + "type": "string" + }, + { + "name": "is_initialized", + "type": "bool" + }, + { + "name": "side_won", + "type": { + "option": "u8" + } + }, + { + "name": "expiration_at", + "type": "i64" + }, + { + "name": "created_at", + "type": "i64" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "fee_bps", + "type": "u16" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/market-maker-bot/src/index.ts b/packages/market-maker-bot/src/index.ts index b5cb6711..e298ff76 100644 --- a/packages/market-maker-bot/src/index.ts +++ b/packages/market-maker-bot/src/index.ts @@ -17,8 +17,13 @@ import { } from "@hyperbet/chain-registry"; import { DEFAULT_MARKET_MAKER_CONFIG, + DEFAULT_AMM_MARKET_MAKER_CONFIG, buildQuotePlan, + buildAmmTradeDecision, evaluateQuoteDecision, + type AmmMarketMakerConfig, + type AmmMarketSnapshot, + type AmmTradeDecision, type MarketMakerConfig, type MarketSnapshot, } from "@hyperbet/mm-core"; @@ -37,6 +42,7 @@ import dotenv from "dotenv"; import { ethers } from "ethers"; import goldClobMarketIdl from "./idl/gold_clob_market.json" with { type: "json" }; +import lvrAmmIdl from "./idl/lvr_amm.json" with { type: "json" }; import { duelKeyHexToBytes, findClobVaultPda, @@ -47,7 +53,13 @@ import { ORDER_BEHAVIOR_GTC, findPriceLevelPda, findUserBalancePda, + findAmmConfigPda, + findAmmAdminStatePda, + findAmmBetPda, + findAmmMintYesPda, + findAmmMintNoPda, } from "./solana-helpers.ts"; +import { calcAmmPrice, calcDynamicLiquidity, estimateSlippage } from "./amm-math.ts"; import { createDefaultMarketMakerStateStore, type ClaimBacklogInput, @@ -66,6 +78,10 @@ const SHARE_UNIT_SIZE = 1_000n; const EVM_ORDER_FLAG_GTC = 0x01; const OUTBOX_LEASE_MS = 60_000; const CLAIM_BACKLOG_LEASE_MS = 60_000; +const TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); +const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey( + "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", +); const GOLD_CLOB_ABI = [ "function marketKey(bytes32 duelKey, uint8 marketKind) view returns (bytes32)", @@ -121,6 +137,8 @@ type EvmRuntime = { goldClobAddress: string; }; +type EvmNonceRuntime = Pick; + type SignableTx = Transaction | VersionedTransaction; type AnchorLikeWallet = Wallet & { payer: Keypair; @@ -153,6 +171,82 @@ type SolanaManagedOrder = { remainingRawAmount: bigint; }; +// --- AMM runtime types --- + +type SolanaAmmConfig = { + authority: PublicKey; + treasury: PublicKey; + marketMaker: PublicKey; + fightOracleProgram: PublicKey; + feeBps: number; + paused: boolean; +}; + +type SolanaAmmRuntime = { + connection: Connection; + provider: AnchorProvider; + wallet: Keypair; + walletAddress: string; + fightOracleProgramId: PublicKey; + ammProgramId: PublicKey; + ammProgram: Program; + ammConfigPda: PublicKey; + ammAdminStatePda: PublicKey; + ammConfig: SolanaAmmConfig | null; + rpcUrl: string; +}; + +type EvmAmmRuntime = { + chainKey: BettingEvmChain; + enabled: boolean; + provider: ethers.JsonRpcProvider; + wallet: ethers.Wallet; + walletAddress: string; + router: ethers.Contract; + mUsd: ethers.Contract; + routerAddress: string; + rpcUrl: string; +}; + +type AmmPosition = { + chainKey: BettingChainKey; + marketRef: string; + betId: string; + creator: string; + yesBalance: bigint; + noBalance: bigint; + costBasis: bigint; + settled: boolean; +}; + +const GOLD_AMM_ROUTER_ABI = [ + "function buyYes(address market, uint256 collateralIn, uint256 minAmountOut)", + "function buyNo(address market, uint256 collateralIn, uint256 minAmountOut)", + "function sellYes(address market, uint256 tokenIn, uint256 minAmountOut)", + "function sellNo(address market, uint256 tokenIn, uint256 minAmountOut)", + "function settleFromOracle(address market)", + "function redeem(address market, uint256 amountYes, uint256 amountNo)", + "function getAllMarkets() view returns (address[])", + "function mUSD() view returns (address)", +] as const; + +const LVR_MARKET_ABI = [ + "function state() view returns (uint8)", + "function getMarketDetails() view returns (uint8, uint256, uint256, uint256, uint256, uint256, uint256, uint256)", + "function getPriceYes() view returns (uint256)", + "function getPriceNo() view returns (uint256)", + "function yesToken() view returns (address)", + "function noToken() view returns (address)", + "function feeBps() view returns (uint256)", + "function isDynamic() view returns (bool)", +] as const; + +const ERC20_ABI = [ + "function balanceOf(address) view returns (uint256)", + "function approve(address spender, uint256 amount) returns (bool)", + "function allowance(address owner, address spender) view returns (uint256)", +] as const; + type CrossChainMarketMakerOptions = { stateStore?: MarketMakerStateStore; }; @@ -172,6 +266,13 @@ function readEnvNumber(name: string, fallback: number): number { return Number.isFinite(parsed) ? parsed : fallback; } +function findAssociatedTokenAddress(mint: PublicKey, owner: PublicKey): PublicKey { + return PublicKey.findProgramAddressSync( + [owner.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()], + ASSOCIATED_TOKEN_PROGRAM_ID, + )[0]; +} + function parseEnvironment(raw: string | undefined): BettingAppEnvironment { switch ((raw ?? "").trim().toLowerCase()) { case "local": @@ -626,6 +727,14 @@ export class CrossChainMarketMaker { private lastPredictionMarkets: PredictionMarketsResponse | null = null; private lastPredictionMarketsAt = 0; + // AMM state + private readonly evmAmmRuntimes: EvmAmmRuntime[]; + private readonly solanaAmmRuntime: SolanaAmmRuntime | null; + private readonly ammPositions = new Map(); + private ammEnabled = readEnvBoolean("MM_ENABLE_AMM", true); + private ammSolanaEnabled = readEnvBoolean("MM_ENABLE_AMM_SOLANA", true); + private readonly ammConfig: AmmMarketMakerConfig; + constructor(options: CrossChainMarketMakerOptions = {}) { this.instanceId = (process.env.MM_INSTANCE_ID || "mm-1").trim() || "mm-1"; this.config = buildMarketMakerConfig(); @@ -635,6 +744,21 @@ export class CrossChainMarketMaker { this.createEvmRuntime(chainKey), ); this.solanaRuntime = this.createSolanaRuntime(); + + // AMM runtimes + this.ammConfig = { + ...DEFAULT_AMM_MARKET_MAKER_CONFIG, + deviationThresholdBps: readEnvNumber("MM_AMM_DEVIATION_THRESHOLD_BPS", DEFAULT_AMM_MARKET_MAKER_CONFIG.deviationThresholdBps), + maxTradeSize: readEnvNumber("MM_AMM_MAX_TRADE_SIZE", DEFAULT_AMM_MARKET_MAKER_CONFIG.maxTradeSize), + minTradeSize: readEnvNumber("MM_AMM_MIN_TRADE_SIZE", DEFAULT_AMM_MARKET_MAKER_CONFIG.minTradeSize), + maxPositionSize: readEnvNumber("MM_AMM_MAX_POSITION_SIZE", DEFAULT_AMM_MARKET_MAKER_CONFIG.maxPositionSize), + }; + this.evmAmmRuntimes = this.ammEnabled + ? BETTING_EVM_CHAIN_ORDER.map((chainKey) => this.createEvmAmmRuntime(chainKey)) + : []; + this.solanaAmmRuntime = this.ammEnabled && this.ammSolanaEnabled + ? this.createSolanaAmmRuntime() + : null; } private async ensureStateStoreReady() { @@ -1600,6 +1724,17 @@ export class CrossChainMarketMaker { } await this.solanaMarketMake(predictionMarkets, duelSignal); + + // AMM market-making (parallel to CLOB above) + if (this.ammEnabled) { + for (const runtime of this.evmAmmRuntimes) { + if (!runtime.enabled) continue; + await this.evmAmmMarketMake(runtime, predictionMarkets, duelSignal); + } + if (this.ammSolanaEnabled && this.solanaAmmRuntime) { + await this.solanaAmmMarketMake(predictionMarkets, duelSignal); + } + } } private async evmMarketMake( @@ -1850,7 +1985,7 @@ export class CrossChainMarketMaker { return null; } - private async nextRuntimeNonce(runtime: EvmRuntime): Promise { + private async nextRuntimeNonce(runtime: EvmNonceRuntime): Promise { const cached = this.nextNonceByChain.get(runtime.chainKey); if (cached != null) { return cached; @@ -1863,14 +1998,14 @@ export class CrossChainMarketMaker { return fresh; } - private noteRuntimeNonceCommitted(runtime: EvmRuntime, nonce: number) { + private noteRuntimeNonceCommitted(runtime: EvmNonceRuntime, nonce: number) { const cached = this.nextNonceByChain.get(runtime.chainKey); if (cached == null || nonce >= cached) { this.nextNonceByChain.set(runtime.chainKey, nonce + 1); } } - private async refreshRuntimeNonce(runtime: EvmRuntime): Promise { + private async refreshRuntimeNonce(runtime: EvmNonceRuntime): Promise { const fresh = await runtime.provider.getTransactionCount( runtime.walletAddress, "pending", @@ -1880,7 +2015,7 @@ export class CrossChainMarketMaker { } private async sendEvmTransaction( - runtime: EvmRuntime, + runtime: EvmNonceRuntime, buildTransaction: (nonce: number) => Promise, ): Promise<{ tx: T; nonce: number }> { const nonce = await this.nextRuntimeNonce(runtime); @@ -2694,12 +2829,623 @@ export class CrossChainMarketMaker { } } + // --- AMM Runtime Creation --- + + private createEvmAmmRuntime(chainKey: BettingEvmChain): EvmAmmRuntime { + const disabled: EvmAmmRuntime = { + chainKey, + enabled: false, + provider: null as any, + wallet: null as any, + walletAddress: "", + router: null as any, + mUsd: null as any, + routerAddress: "", + rpcUrl: "", + }; + try { + const resolved = resolveBettingEvmRuntimeEnv(chainKey, TARGET_ENV); + const routerAddress = resolved.goldAmmRouterAddress?.trim(); + if (!routerAddress) return disabled; + const mUsdAddress = resolved.mUsdTokenAddress?.trim(); + const rpcUrl = resolved.rpcUrl; + const privateKey = ( + process.env[`EVM_PRIVATE_KEY_${chainKey.toUpperCase()}`] || + process.env.EVM_PRIVATE_KEY || + "" + ).trim(); + if (!privateKey) return disabled; + const provider = new ethers.JsonRpcProvider(rpcUrl); + const wallet = new ethers.Wallet(privateKey, provider); + const router = new ethers.Contract(routerAddress, GOLD_AMM_ROUTER_ABI, wallet); + const mUsd = mUsdAddress + ? new ethers.Contract(mUsdAddress, ERC20_ABI, wallet) + : (null as any); + return { + chainKey, + enabled: true, + provider, + wallet, + walletAddress: wallet.address, + router, + mUsd, + routerAddress, + rpcUrl, + }; + } catch (err) { + console.warn(`[AMM] Failed to create EVM AMM runtime for ${chainKey}:`, err); + return disabled; + } + } + + private createSolanaAmmRuntime(): SolanaAmmRuntime | null { + if (!this.ammSolanaEnabled) return null; + const solanaPrivateKey = (process.env.SOLANA_PRIVATE_KEY || "").trim(); + if (!solanaPrivateKey) return null; + try { + const deployment = resolveBettingSolanaDeployment( + normalizeSolanaCluster(TARGET_ENV) as any, + ); + const ammProgramIdStr = ( + process.env.GOLD_AMM_MARKET_PROGRAM_ID || "" + ).trim() || deployment.goldAmmMarketProgramId; + if (!ammProgramIdStr) return null; + const ammProgramId = new PublicKey(ammProgramIdStr); + const rpcUrl = + (process.env.SOLANA_RPC_URL || "").trim() || + defaultSolanaRpcUrl(TARGET_ENV); + const keyBytes = decodeSolanaSecretKey(solanaPrivateKey); + const wallet = + keyBytes.length === 32 + ? Keypair.fromSeed(keyBytes) + : Keypair.fromSecretKey(keyBytes); + const connection = new Connection(rpcUrl, "confirmed"); + const provider = new AnchorProvider( + connection, + toAnchorWallet(wallet), + { commitment: "confirmed", preflightCommitment: "confirmed" }, + ); + const fightOracleProgramId = new PublicKey( + (process.env.FIGHT_ORACLE_PROGRAM_ID || "").trim() || + deployment.fightOracleProgramId, + ); + const ammProgram = new Program( + ensureIdlAddress(lvrAmmIdl, ammProgramId), + provider, + ) as Program; + return { + connection, + provider, + wallet, + walletAddress: wallet.publicKey.toBase58(), + fightOracleProgramId, + ammProgramId, + ammProgram, + ammConfigPda: findAmmConfigPda(ammProgramId), + ammAdminStatePda: findAmmAdminStatePda(ammProgramId), + ammConfig: null, + rpcUrl, + }; + } catch (error) { + console.warn( + `[AMM-SOLANA] Disabled: ${error instanceof Error ? error.message : String(error)}`, + ); + return null; + } + } + + // --- AMM Market-Making Cycle --- + + private async solanaAmmMarketMake( + predictionMarkets: PredictionMarketsResponse | null, + duelSignal: DuelSignal | null, + ) { + const runtime = this.solanaAmmRuntime; + if (!this.ammEnabled || !this.ammSolanaEnabled || !runtime) return; + + // Fetch ammConfig on first cycle + if (!runtime.ammConfig) { + try { + const configAccount = await (runtime.ammProgram.account as any).ammConfig.fetchNullable( + runtime.ammConfigPda, + ); + if (!configAccount) return; + runtime.ammConfig = { + authority: configAccount.authority, + treasury: configAccount.treasury, + marketMaker: configAccount.marketMaker, + fightOracleProgram: configAccount.fightOracleProgram, + feeBps: configAccount.feeBps, + paused: configAccount.paused, + }; + } catch { + return; + } + } + if (runtime.ammConfig.paused) return; + + // Find AMM markets from lifecycle records + const ammMarkets = (predictionMarkets?.markets ?? []).filter( + (m) => m.chainKey === "solana" && m.marketType === "amm", + ); + + for (const market of ammMarkets) { + try { + await this.solanaAmmMarketMakeOne(runtime, market, duelSignal); + } catch (error) { + console.warn( + `[AMM-SOLANA] market-make error for ${market.marketRef}: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } + } + + private async solanaAmmMarketMakeOne( + runtime: SolanaAmmRuntime, + market: PredictionMarketLifecycleRecord, + duelSignal: DuelSignal | null, + ) { + const metadata = market.metadata as Record | undefined; + const betId = BigInt((metadata?.betId as string) || "0"); + const creatorStr = (metadata?.creator as string) || ""; + if (!betId || !creatorStr) return; + const creator = new PublicKey(creatorStr); + + const betPda = findAmmBetPda(runtime.ammProgramId, betId, creator); + + // Fetch bet state + const betAccount = await (runtime.ammProgram.account as any).bet.fetchNullable(betPda); + if (!betAccount || !betAccount.isInitialized) return; + + // Check if settled + if (betAccount.sideWon != null) { + await this.solanaAmmWithdraw(runtime, betId, creator, betAccount); + return; + } + + // Compute price + const reserveYes = BigInt(betAccount.reserves[0].toString()); + const reserveNo = BigInt(betAccount.reserves[1].toString()); + const currentTime = BigInt(Math.floor(Date.now() / 1000)); + const liq = betAccount.isDynamic + ? calcDynamicLiquidity(BigInt(betAccount.initialLiq.toString()), BigInt(betAccount.expirationAt.toString()), currentTime) + : BigInt(betAccount.initialLiq.toString()); + const ammPrice = calcAmmPrice(reserveYes, reserveNo, liq); + + // Build snapshot + const posKey = `solana:${betPda.toBase58()}`; + const existing = this.ammPositions.get(posKey); + const snapshot: AmmMarketSnapshot = { + chainKey: "solana", + lifecycleStatus: market.lifecycleStatus, + duelKey: market.duelKey, + marketRef: betPda.toBase58(), + ammPriceYes: ammPrice, + reserveYes: Number(reserveYes), + reserveNo: Number(reserveNo), + liquidity: Number(liq), + betCloseTimeMs: betAccount.expirationAt + ? Number(betAccount.expirationAt) * 1000 + : null, + lastStreamAtMs: Date.now(), + lastOracleAtMs: Date.now(), + lastRpcAtMs: Date.now(), + exposure: { + yes: Number(existing?.yesBalance ?? 0n), + no: Number(existing?.noBalance ?? 0n), + openYes: 0, + openNo: 0, + }, + }; + + const signal = duelSignal + ? { signalPrice: duelSignal.midPrice, signalWeight: duelSignal.weight } + : {}; + const decision = buildAmmTradeDecision(snapshot, signal, this.ammConfig); + + if (decision.action === "hold") return; + + const outcome = decision.action === "buy_yes" || decision.action === "sell_yes" ? 0 : 1; + const amountIn = new BN(decision.amount); + const mintYes = findAmmMintYesPda(runtime.ammProgramId, betId, creator); + const mintNo = findAmmMintNoPda(runtime.ammProgramId, betId, creator); + const destinationYes = findAssociatedTokenAddress(mintYes, runtime.wallet.publicKey); + const destinationNo = findAssociatedTokenAddress(mintNo, runtime.wallet.publicKey); + const treasuryYesAta = findAssociatedTokenAddress( + mintYes, + runtime.ammConfig!.treasury, + ); + const treasuryNoAta = findAssociatedTokenAddress( + mintNo, + runtime.ammConfig!.treasury, + ); + + const isBuy = decision.action === "buy_yes" || decision.action === "buy_no"; + + try { + if (isBuy) { + await runtime.ammProgram.methods + .buy(new BN(betId.toString()), outcome, amountIn) + .accountsPartial({ + signer: runtime.wallet.publicKey, + ammConfig: runtime.ammConfigPda, + bet: betPda, + treasury: runtime.ammConfig!.treasury, + mintYes, + mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .rpc(); + } else { + await runtime.ammProgram.methods + .sell(new BN(betId.toString()), outcome, amountIn) + .accountsPartial({ + signer: runtime.wallet.publicKey, + ammConfig: runtime.ammConfigPda, + bet: betPda, + treasury: runtime.ammConfig!.treasury, + mintYes, + mintNo, + destinationYes, + destinationNo, + treasuryYesAta, + treasuryNoAta, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .rpc(); + } + + // Read actual token balances after trade for accurate position tracking + const [yesBalResp, noBalResp] = await Promise.all([ + runtime.connection.getTokenAccountBalance(destinationYes).catch(() => ({ + value: { amount: "0" }, + })), + runtime.connection.getTokenAccountBalance(destinationNo).catch(() => ({ + value: { amount: "0" }, + })), + ]); + + const pos: AmmPosition = existing ?? { + chainKey: "solana", + marketRef: betPda.toBase58(), + betId: betId.toString(), + creator: creatorStr, + yesBalance: 0n, + noBalance: 0n, + costBasis: 0n, + settled: false, + }; + pos.yesBalance = BigInt(yesBalResp.value.amount); + pos.noBalance = BigInt(noBalResp.value.amount); + if (isBuy) { + pos.costBasis += BigInt(decision.amount); + } + this.ammPositions.set(posKey, pos); + } catch (error) { + console.warn( + `[AMM-SOLANA] ${decision.action} failed: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } + + private async solanaAmmWithdraw( + runtime: SolanaAmmRuntime, + betId: bigint, + creator: PublicKey, + betAccount: any, + ) { + const posKey = `solana:${findAmmBetPda(runtime.ammProgramId, betId, creator).toBase58()}`; + const pos = this.ammPositions.get(posKey); + if (!pos || pos.settled) return; + + try { + const betPda = findAmmBetPda(runtime.ammProgramId, betId, creator); + const mintYes = findAmmMintYesPda(runtime.ammProgramId, betId, creator); + const mintNo = findAmmMintNoPda(runtime.ammProgramId, betId, creator); + const destinationYes = findAssociatedTokenAddress( + mintYes, + runtime.wallet.publicKey, + ); + const destinationNo = findAssociatedTokenAddress( + mintNo, + runtime.wallet.publicKey, + ); + const [yesBalanceResp, noBalanceResp] = await Promise.all([ + runtime.connection.getTokenAccountBalance(destinationYes).catch(() => ({ + value: { amount: "0" }, + })), + runtime.connection.getTokenAccountBalance(destinationNo).catch(() => ({ + value: { amount: "0" }, + })), + ]); + + const yesBalance = BigInt(yesBalanceResp.value.amount); + const noBalance = BigInt(noBalanceResp.value.amount); + const sideWon: number = Number(betAccount.sideWon); + const withdrawals: Array<{ outcome: number; balance: bigint }> = []; + + if (sideWon === 2) { + if (yesBalance > 0n) withdrawals.push({ outcome: 0, balance: yesBalance }); + if (noBalance > 0n) withdrawals.push({ outcome: 1, balance: noBalance }); + } else if (sideWon === 0 && yesBalance > 0n) { + withdrawals.push({ outcome: 0, balance: yesBalance }); + } else if (sideWon === 1 && noBalance > 0n) { + withdrawals.push({ outcome: 1, balance: noBalance }); + } + + if (withdrawals.length === 0) { + pos.settled = true; + return; + } + + for (const withdrawal of withdrawals) { + await runtime.ammProgram.methods + .withdrawPostSettle( + new BN(betId.toString()), + withdrawal.outcome, + new BN(withdrawal.balance.toString()), + ) + .accountsPartial({ + signer: runtime.wallet.publicKey, + bet: betPda, + mintYes, + mintNo, + destinationYes, + destinationNo, + tokenProgram: TOKEN_PROGRAM_ID, + systemProgram: SystemProgram.programId, + associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID, + }) + .rpc(); + } + + pos.settled = true; + console.log(`[AMM-SOLANA] withdrew from settled bet ${betId}`); + } catch (error) { + console.warn( + `[AMM-SOLANA] withdraw failed for bet ${betId}: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } + + private async evmAmmMarketMake( + runtime: EvmAmmRuntime, + predictionMarkets: PredictionMarketsResponse | null, + duelSignal: DuelSignal | null, + ) { + if (!runtime.enabled) return; + + const ammMarkets = (predictionMarkets?.markets ?? []).filter( + (m) => m.chainKey === runtime.chainKey && m.marketType === "amm", + ); + + for (const market of ammMarkets) { + try { + await this.evmAmmMarketMakeOne(runtime, market, duelSignal); + } catch (error) { + console.warn( + `[AMM-${runtime.chainKey.toUpperCase()}] error: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } + } + + private async evmAmmMarketMakeOne( + runtime: EvmAmmRuntime, + market: PredictionMarketLifecycleRecord, + duelSignal: DuelSignal | null, + ) { + const marketAddress = market.contractAddress ?? market.marketRef; + if (!marketAddress) return; + + const lvrMarket = new ethers.Contract(marketAddress, LVR_MARKET_ABI, runtime.provider); + const [stateRaw, deadlineRaw, , liqRaw, reserveYesRaw, reserveNoRaw] = + await lvrMarket.getMarketDetails(); + + // state: 0=OPEN, 1=CLOSED, 2=PENDING, 3=DISPUTED, 4=RESOLVED + const marketState = Number(stateRaw); + if (marketState === 4) { + await this.evmAmmRedeem(runtime, marketAddress); + return; + } + if (marketState !== 0) return; + + // Compute price using EVM WAD (1e18) reserves — normalize to [0, 1] + // We use the Solana math port (1e6 scale) by downscaling + const scale = 1_000_000_000_000n; // 1e18 / 1e6 + const ry = BigInt(reserveYesRaw.toString()) / scale; + const rn = BigInt(reserveNoRaw.toString()) / scale; + const l = BigInt(liqRaw.toString()) / scale; + const ammPrice = calcAmmPrice(ry, rn, l); + + const posKey = `${runtime.chainKey}:${marketAddress}`; + const existing = this.ammPositions.get(posKey); + + const now = Date.now(); + const snapshot: AmmMarketSnapshot = { + chainKey: runtime.chainKey, + lifecycleStatus: market.lifecycleStatus, + duelKey: market.duelKey, + marketRef: marketAddress, + ammPriceYes: ammPrice, + reserveYes: Number(ry), + reserveNo: Number(rn), + liquidity: Number(l), + betCloseTimeMs: Number(deadlineRaw) * 1000, + lastStreamAtMs: now, // AMM uses on-chain state, no separate stream + lastOracleAtMs: now, + lastRpcAtMs: now, + exposure: { + // Normalize WAD (1e18) token balances to human-readable units + yes: Number((existing?.yesBalance ?? 0n) / 1_000_000_000_000_000_000n), + no: Number((existing?.noBalance ?? 0n) / 1_000_000_000_000_000_000n), + openYes: 0, + openNo: 0, + }, + }; + + const signal = duelSignal + ? { signalPrice: duelSignal.midPrice, signalWeight: duelSignal.weight } + : {}; + const decision = buildAmmTradeDecision(snapshot, signal, this.ammConfig); + + if (decision.action === "hold") return; + + const amountBn = ethers.parseUnits(decision.amount.toString(), 18); // mUSD WAD (18 decimals) + + // Compute slippage-protected minAmountOut (2% tolerance) + const isBuyAction = decision.action === "buy_yes" || decision.action === "buy_no"; + const isBuyYesAction = decision.action === "buy_yes" || decision.action === "sell_no"; + const { amountOut: expectedOut } = estimateSlippage( + isBuyYesAction, BigInt(ry.toString()), BigInt(rn.toString()), BigInt(l.toString()), + BigInt(amountBn.toString()) / 1_000_000_000_000n, // scale WAD to u64 1e6 + ); + const slippageBps = BigInt(this.ammConfig.maxSlippageBps ?? 200); + // Scale minAmountOut back to WAD for the router + const minAmountOut = (expectedOut * (10000n - slippageBps) / 10000n) * 1_000_000_000_000n; + + try { + if (isBuyAction) { + // Ensure mUSD approval (use nonce tracker for all EVM txs) + if (runtime.mUsd) { + const allowance = await runtime.mUsd.allowance( + runtime.walletAddress, + runtime.routerAddress, + ); + if (BigInt(allowance.toString()) < BigInt(amountBn.toString())) { + await this.sendEvmTransaction(runtime, (nonce) => + runtime.mUsd!.approve(runtime.routerAddress, ethers.MaxUint256, { nonce }), + ); + } + } + if (decision.action === "buy_yes") { + await this.sendEvmTransaction(runtime, (nonce) => + runtime.router.buyYes(marketAddress, amountBn, minAmountOut, { nonce }), + ); + } else { + await this.sendEvmTransaction(runtime, (nonce) => + runtime.router.buyNo(marketAddress, amountBn, minAmountOut, { nonce }), + ); + } + } else { + // Sell: need token approval + const [yesTokenAddr, noTokenAddr] = await Promise.all([ + lvrMarket.yesToken(), + lvrMarket.noToken(), + ]); + const tokenAddr = decision.action === "sell_yes" ? yesTokenAddr : noTokenAddr; + const token = new ethers.Contract(tokenAddr, ERC20_ABI, runtime.wallet); + const allowance = await token.allowance(runtime.walletAddress, runtime.routerAddress); + if (BigInt(allowance.toString()) < BigInt(amountBn.toString())) { + await this.sendEvmTransaction(runtime, (nonce) => + token.approve(runtime.routerAddress, ethers.MaxUint256, { nonce }), + ); + } + if (decision.action === "sell_yes") { + await this.sendEvmTransaction(runtime, (nonce) => + runtime.router.sellYes(marketAddress, amountBn, minAmountOut, { nonce }), + ); + } else { + await this.sendEvmTransaction(runtime, (nonce) => + runtime.router.sellNo(marketAddress, amountBn, minAmountOut, { nonce }), + ); + } + } + + // Read actual token balances after trade + const [yesTokenAddr, noTokenAddr] = await Promise.all([ + lvrMarket.yesToken(), + lvrMarket.noToken(), + ]); + const yesToken = new ethers.Contract(yesTokenAddr, ERC20_ABI, runtime.provider); + const noToken = new ethers.Contract(noTokenAddr, ERC20_ABI, runtime.provider); + const [yesBal, noBal] = await Promise.all([ + yesToken.balanceOf(runtime.walletAddress), + noToken.balanceOf(runtime.walletAddress), + ]); + + const pos: AmmPosition = existing ?? { + chainKey: runtime.chainKey, + marketRef: marketAddress, + betId: "0", + creator: "", + yesBalance: 0n, + noBalance: 0n, + costBasis: 0n, + settled: false, + }; + pos.yesBalance = BigInt(yesBal.toString()); + pos.noBalance = BigInt(noBal.toString()); + if (decision.action === "buy_yes" || decision.action === "buy_no") { + pos.costBasis += BigInt(decision.amount); + } + this.ammPositions.set(posKey, pos); + } catch (error) { + console.warn( + `[AMM-${runtime.chainKey.toUpperCase()}] ${decision.action} failed: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } + + private async evmAmmRedeem(runtime: EvmAmmRuntime, marketAddress: string) { + const posKey = `${runtime.chainKey}:${marketAddress}`; + const pos = this.ammPositions.get(posKey); + if (!pos || pos.settled) return; + if (pos.yesBalance <= 0n && pos.noBalance <= 0n) { + pos.settled = true; + return; + } + try { + const lvrMarket = new ethers.Contract(marketAddress, LVR_MARKET_ABI, runtime.provider); + const [yesTokenAddr, noTokenAddr] = await Promise.all([ + lvrMarket.yesToken(), + lvrMarket.noToken(), + ]); + // Approve both tokens + for (const addr of [yesTokenAddr, noTokenAddr]) { + const token = new ethers.Contract(addr, ERC20_ABI, runtime.wallet); + const allowance = await token.allowance(runtime.walletAddress, runtime.routerAddress); + if (BigInt(allowance.toString()) < ethers.MaxUint256 / 2n) { + await token.approve(runtime.routerAddress, ethers.MaxUint256); + } + } + await runtime.router.redeem(marketAddress, pos.yesBalance, pos.noBalance); + pos.settled = true; + console.log(`[AMM-${runtime.chainKey.toUpperCase()}] redeemed from ${marketAddress}`); + } catch (error) { + console.warn( + `[AMM-${runtime.chainKey.toUpperCase()}] redeem failed: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } + + getAmmPositions() { + return [...this.ammPositions.entries()].map(([key, pos]) => ({ + key, + ...pos, + yesBalance: pos.yesBalance.toString(), + noBalance: pos.noBalance.toString(), + costBasis: pos.costBasis.toString(), + })); + } + getInventory() { - const aggregate = { yes: 0, no: 0 }; + const aggregate = { yes: 0, no: 0, ammYes: 0, ammNo: 0 }; for (const exposure of this.exposureByChain.values()) { aggregate.yes += exposure.yes; aggregate.no += exposure.no; } + for (const pos of this.ammPositions.values()) { + // Normalize WAD (1e18) to human-readable + aggregate.ammYes += Number(pos.yesBalance / 1_000_000_000_000_000_000n); + aggregate.ammNo += Number(pos.noBalance / 1_000_000_000_000_000_000n); + } return aggregate; } @@ -2735,6 +3481,15 @@ export class CrossChainMarketMaker { solanaRpcUrl: runtime?.rpcUrl ?? null, solanaLastSuccessfulRpcAt: this.lastSuccessfulSolanaRpcAt, solanaLastTxSignature: this.lastSolanaTxSignature, + ammEnabled: this.ammEnabled, + ammSolanaEnabled: this.ammSolanaEnabled, + ammSolanaProgramId: this.solanaAmmRuntime?.ammProgramId.toBase58() ?? null, + ammEvmChains: Object.fromEntries( + this.evmAmmRuntimes.map((r) => [r.chainKey, r.enabled]), + ), + ammDeviationThresholdBps: this.ammConfig.deviationThresholdBps, + ammMaxTradeSize: this.ammConfig.maxTradeSize, + ammPositionCount: this.ammPositions.size, }; } } diff --git a/packages/market-maker-bot/src/local-sim.ts b/packages/market-maker-bot/src/local-sim.ts new file mode 100644 index 00000000..9e19c5e4 --- /dev/null +++ b/packages/market-maker-bot/src/local-sim.ts @@ -0,0 +1,749 @@ +/** + * Local end-to-end MM simulator. + * + * Starts anvil, deploys Oracle + CLOB + MockUSD + AMM Router, creates both + * CLOB and AMM markets, spins up a stub API server, funds wallets, and runs + * the CrossChainMarketMaker through full market-making cycles on both market + * types. + * + * Usage: + * bun run src/local-sim.ts [--chain bsc] [--cycles 10] + */ +import { strict as assert } from "node:assert"; +import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; +import { readFile } from "node:fs/promises"; +import { spawn, type ChildProcess } from "node:child_process"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +import { ethers } from "ethers"; +import type { BettingEvmChain } from "@hyperbet/chain-registry"; +import { createTestMarketMakerStateStore } from "./storage/index.ts"; + +// ─── Constants ─────────────────────────────────────────────────────────────── + +const ANVIL_PORT = 28545; +const ANVIL_RPC_URL = `http://127.0.0.1:${ANVIL_PORT}`; +const ANVIL_CHAIN_ID = 31337; + +const MARKET_KIND_DUEL_WINNER = 0; +const DUEL_STATUS_BETTING_OPEN = 2; +const BUY_SIDE = 1; +const SELL_SIDE = 2; +const ORDER_FLAG_GTC = 0x01; +const MAX_PRICE = 1000; +const SHARE_UNIT_SIZE = 1_000n; +const DISPUTE_WINDOW_SECONDS = 3_600; + +const DEFAULT_PRIVATE_KEYS = [ + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "0x59c6995e998f97a5a0044966f0945382d7d46f71fbb8f7a1a5b2d3c6f90ad7d4", + "0x5de4111afa1a4b94908b95ad9b8e4f5ff3a5f9d1f0e8f8dd3c9a1f4f2b7c6d5e", + "0x7c852118294d6d4f0c3d1e4b4a1a278e6b8980c97c7c1b3e76aa87e3112e7854", + "0x47e179ec19748874f6b4b93b5e1f0a421c7b0f52ce6f5c4f0b1e4a962f8d8338", + "0x8b3a350cf5c34c9194ca3a545d8a7d3a8d2c2e0f28c52f4fb151797f63018e8d", + "0x92db14e403f6dc6cc99d4d1d5bf4d70e2e7a55d499c19de577f4d3e42c8f2b29", +] as const; + +// ─── Types ─────────────────────────────────────────────────────────────────── + +type Artifact = { + abi: readonly unknown[]; + bytecode: { object: string }; +}; + +type StubState = { + duelKey: string; + duelId: string; + marketStatus: "OPEN" | "LOCKED"; + phase: "FIGHTING" | "COUNTDOWN"; + betCloseTime: number; + updatedAt: number; + hpA: number; + hpB: number; + ammMarketAddress: string | null; +}; + +type RuntimeContract = ethers.Contract & Record; + +// ─── Helpers ───────────────────────────────────────────────────────────────── + +function parseArgs(): { chain: BettingEvmChain; cycles: number } { + const args = process.argv.slice(2); + const getValue = (flag: string, fallback: string) => { + const index = args.indexOf(flag); + if (index === -1) return fallback; + const value = args[index + 1]; + return value && !value.startsWith("--") ? value : fallback; + }; + const chain = getValue("--chain", "bsc").trim().toLowerCase(); + if (chain !== "bsc" && chain !== "base" && chain !== "avax") { + throw new Error(`unsupported chain ${chain}`); + } + return { + chain, + cycles: Math.max(1, parseInt(getValue("--cycles", "10"), 10) || 10), + }; +} + +type FullArtifact = Artifact & { + bytecode: Artifact["bytecode"] & { + linkReferences?: Record>; + }; +}; + +async function loadArtifact(relativePath: string): Promise { + const here = path.dirname(fileURLToPath(import.meta.url)); + const artifactPath = path.resolve(here, "../../evm-contracts/out", relativePath); + return JSON.parse(await readFile(artifactPath, "utf8")) as FullArtifact; +} + +/** + * Link library addresses into bytecode that has unresolved link references. + * Foundry uses `__$$__` placeholders. We extract the placeholder from + * the first known position then do a global string replace — this covers both + * the init code AND the embedded LvrMarket creation code in the runtime. + */ +function linkBytecode( + artifact: FullArtifact, + libraries: Record, +): string { + let bytecode = artifact.bytecode.object; + const refs = artifact.bytecode.linkReferences ?? {}; + for (const [filePath, libs] of Object.entries(refs)) { + for (const [libName, positions] of Object.entries(libs)) { + const key = `${filePath}:${libName}`; + const address = libraries[key]; + if (!address) { + throw new Error(`missing library address for ${key}`); + } + const addrHex = address.replace("0x", "").toLowerCase().padStart(40, "0"); + // Extract the placeholder string from the first known position + const firstPos = positions[0]; + const hexStart = 2 + firstPos.start * 2; + const placeholder = bytecode.slice(hexStart, hexStart + 40); + // Replace ALL occurrences globally (init code + embedded runtime) + bytecode = bytecode.replaceAll(placeholder, addrHex); + } + } + return bytecode; +} + +function duelKey(label: string): string { + return ethers.keccak256(ethers.toUtf8Bytes(label)); +} + +function participantHash(label: string): string { + return ethers.keccak256(ethers.toUtf8Bytes(label)); +} + +function quoteCost(side: number, price: number, amount: bigint): bigint { + const component = BigInt(side === BUY_SIDE ? price : MAX_PRICE - price); + return (amount * component) / BigInt(MAX_PRICE); +} + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +// ─── Anvil ─────────────────────────────────────────────────────────────────── + +async function startAnvil(): Promise { + // Kill any stale anvil on this port + try { + const { execSync } = await import("node:child_process"); + const pids = execSync(`lsof -tiTCP:${ANVIL_PORT} -sTCP:LISTEN 2>/dev/null || true`, { + encoding: "utf8", + }).trim(); + for (const pid of pids.split("\n").filter(Boolean)) { + try { process.kill(parseInt(pid, 10)); } catch {} + } + } catch {} + + console.log(`[local-sim] starting anvil on port ${ANVIL_PORT}...`); + const anvil = spawn("anvil", [ + "--silent", + "--accounts", "20", + "--host", "127.0.0.1", + "--port", String(ANVIL_PORT), + "--chain-id", String(ANVIL_CHAIN_ID), + ], { stdio: "ignore" }); + + // Wait for RPC readiness + for (let i = 0; i < 60; i++) { + try { + const response = await fetch(ANVIL_RPC_URL, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", method: "eth_blockNumber", params: [], id: 1 }), + }); + const json = await response.json() as any; + if (json.result) { + console.log("[local-sim] anvil ready"); + return anvil; + } + } catch {} + await sleep(500); + } + anvil.kill(); + throw new Error("anvil did not become ready within 30s"); +} + +// ─── Stub API Server ───────────────────────────────────────────────────────── + +function sendJson(res: ServerResponse, payload: unknown) { + res.statusCode = 200; + res.setHeader("content-type", "application/json"); + res.end(JSON.stringify(payload)); +} + +async function startStubServer( + chain: BettingEvmChain, + state: StubState, +): Promise<{ apiUrl: string; duelUrl: string; close: () => Promise }> { + const server = createServer((req: IncomingMessage, res: ServerResponse) => { + const url = new URL(req.url || "/", "http://127.0.0.1"); + + if (url.pathname === "/api/arena/prediction-markets/active") { + const markets: any[] = [ + // CLOB market + { + chainKey: chain, + duelKey: state.duelKey, + duelId: state.duelId, + marketId: `${chain}-${state.duelId}`, + marketRef: null, + lifecycleStatus: state.marketStatus, + winner: "NONE", + betCloseTime: state.betCloseTime, + contractAddress: null, + programId: null, + txRef: null, + syncedAt: state.updatedAt, + marketType: "clob", + }, + ]; + + // AMM market (if deployed) + if (state.ammMarketAddress) { + markets.push({ + chainKey: chain, + duelKey: state.duelKey, + duelId: state.duelId, + marketId: `${chain}-amm-${state.duelId}`, + marketRef: state.ammMarketAddress, + lifecycleStatus: state.marketStatus, + winner: "NONE", + betCloseTime: state.betCloseTime, + contractAddress: state.ammMarketAddress, + programId: null, + txRef: null, + syncedAt: state.updatedAt, + marketType: "amm", + }); + } + + sendJson(res, { + duel: { + duelKey: state.duelKey, + duelId: state.duelId, + phase: state.phase, + betCloseTime: state.betCloseTime, + }, + markets, + updatedAt: state.updatedAt, + }); + return; + } + + if (url.pathname === "/api/streaming/state") { + sendJson(res, { + cycle: { + phase: state.phase, + agent1: { hp: state.hpA, maxHp: 100 }, + agent2: { hp: state.hpB, maxHp: 100 }, + }, + }); + return; + } + + res.statusCode = 404; + res.end("not found"); + }); + + await new Promise((resolve, reject) => { + server.once("error", reject); + server.listen(0, "127.0.0.1", () => resolve()); + }); + const address = server.address(); + if (!address || typeof address === "string") { + throw new Error("failed to bind stub server"); + } + const baseUrl = `http://127.0.0.1:${address.port}`; + return { + apiUrl: `${baseUrl}/api/arena/prediction-markets/active`, + duelUrl: `${baseUrl}/api/streaming/state`, + close: async () => + await new Promise((resolve, reject) => { + server.close((error) => (error ? reject(error) : resolve())); + }), + }; +} + +// ─── Deploy Contracts ──────────────────────────────────────────────────────── + +function createNonceTracker(provider: ethers.JsonRpcProvider) { + const nextNonceByAddress = new Map(); + const tracker = async (address: string) => { + const normalized = address.toLowerCase(); + const cached = nextNonceByAddress.get(normalized); + if (cached != null) { + nextNonceByAddress.set(normalized, cached + 1); + return cached; + } + const fresh = await provider.getTransactionCount(address, "latest"); + nextNonceByAddress.set(normalized, fresh + 1); + return fresh; + }; + tracker.invalidate = (address: string) => { + nextNonceByAddress.delete(address.toLowerCase()); + }; + return tracker; +} + +async function deployContracts(provider: ethers.JsonRpcProvider, chain: BettingEvmChain) { + const [admin, operator, reporter, treasury, marketMakerFeeSink, trader, botSigner] = + DEFAULT_PRIVATE_KEYS.map((pk) => new ethers.Wallet(pk, provider)); + const finalizer = await provider.getSigner(7); + const challenger = await provider.getSigner(8); + const nextNonce = createNonceTracker(provider); + + // Fund actors + const actors = [ + operator.address, + reporter.address, + await finalizer.getAddress(), + await challenger.getAddress(), + treasury.address, + marketMakerFeeSink.address, + trader.address, + botSigner.address, + ]; + console.log("[local-sim] funding wallets..."); + for (const addr of actors) { + await admin.sendTransaction({ + to: addr, + value: ethers.parseEther("50"), + nonce: await nextNonce(admin.address), + }); + } + + // Deploy DuelOutcomeOracle + console.log("[local-sim] deploying DuelOutcomeOracle..."); + const oracleArtifact = await loadArtifact("DuelOutcomeOracle.sol/DuelOutcomeOracle.json"); + const oracleFactory = new ethers.ContractFactory( + oracleArtifact.abi, + oracleArtifact.bytecode.object, + admin, + ); + const oracle = (await oracleFactory.deploy( + admin.address, + reporter.address, + await finalizer.getAddress(), + await challenger.getAddress(), + admin.address, + DISPUTE_WINDOW_SECONDS, + { nonce: await nextNonce(admin.address) }, + )) as RuntimeContract; + await oracle.waitForDeployment(); + console.log(`[local-sim] Oracle: ${await oracle.getAddress()}`); + + // Deploy GoldClob + console.log("[local-sim] deploying GoldClob..."); + const clobArtifact = await loadArtifact("GoldClob.sol/GoldClob.json"); + const clobFactory = new ethers.ContractFactory( + clobArtifact.abi, + clobArtifact.bytecode.object, + admin, + ); + const clob = (await clobFactory.deploy( + admin.address, + operator.address, + await oracle.getAddress(), + treasury.address, + marketMakerFeeSink.address, + admin.address, + { nonce: await nextNonce(admin.address) }, + )) as RuntimeContract; + await clob.waitForDeployment(); + console.log(`[local-sim] CLOB: ${await clob.getAddress()}`); + + // Deploy MockUSD + console.log("[local-sim] deploying MockUSD..."); + const musdArtifact = await loadArtifact("MockUSD.sol/MockUSD.json"); + const musdFactory = new ethers.ContractFactory( + musdArtifact.abi, + musdArtifact.bytecode.object, + admin, + ); + const musd = (await musdFactory.deploy({ + nonce: await nextNonce(admin.address), + })) as RuntimeContract; + await musd.waitForDeployment(); + console.log(`[local-sim] MockUSD: ${await musd.getAddress()}`); + + // Deploy AMM contracts via forge (handles library linking at compile time) + console.log("[local-sim] deploying AMM Router via forge..."); + const { execSync } = await import("node:child_process"); + const evmContractsDir = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + "../../evm-contracts", + ); + const musdAddress = await musd.getAddress(); + const forgeEnv = { ...process.env, PATH: `/opt/homebrew/bin:${process.env.HOME}/.bun/bin:${process.env.PATH}` }; + + // Deploy Math library + const mathOut = execSync( + `forge create contracts/lvr_amm/lib/Math.sol:Math --rpc-url ${ANVIL_RPC_URL} --private-key ${admin.privateKey} --broadcast --json`, + { cwd: evmContractsDir, env: forgeEnv, encoding: "utf8" }, + ); + const mathAddr = JSON.parse(mathOut).deployedTo; + console.log(`[local-sim] Math: ${mathAddr}`); + + // Deploy SwapMath library + const swapOut = execSync( + `forge create contracts/lvr_amm/lib/SwapMath.sol:SwapMath --rpc-url ${ANVIL_RPC_URL} --private-key ${admin.privateKey} --broadcast --json`, + { cwd: evmContractsDir, env: forgeEnv, encoding: "utf8" }, + ); + const swapMathAddr = JSON.parse(swapOut).deployedTo; + console.log(`[local-sim] SwapMath: ${swapMathAddr}`); + + // Deploy Router with linked libraries + const routerOut = execSync( + `forge create contracts/lvr_amm/Router.sol:Router` + + ` --rpc-url ${ANVIL_RPC_URL}` + + ` --private-key ${admin.privateKey}` + + ` --broadcast --json` + + ` --libraries contracts/lvr_amm/lib/Math.sol:Math:${mathAddr}` + + ` --libraries contracts/lvr_amm/lib/SwapMath.sol:SwapMath:${swapMathAddr}` + + ` --constructor-args ${musdAddress} ${treasury.address} 200 ${admin.address} ${await oracle.getAddress()}`, + { cwd: evmContractsDir, env: forgeEnv, encoding: "utf8" }, + ); + const routerAddress = JSON.parse(routerOut).deployedTo; + console.log(`[local-sim] Router: ${routerAddress}`); + + // Forge used admin's nonces directly — invalidate cached nonce so ethers re-fetches + nextNonce.invalidate(admin.address); + + // Create ethers contract instances for the Router and MockUSD + const routerArtifact = await loadArtifact("Router.sol/Router.json"); + const router = new ethers.Contract(routerAddress, routerArtifact.abi, admin) as RuntimeContract; + + // Mint mUSD to admin, trader, and bot for AMM trading + const mintAmount = ethers.parseUnits("1000000", 18); // 1M mUSD + for (const addr of [admin.address, trader.address, botSigner.address]) { + await musd.mint(addr, mintAmount, { nonce: await nextNonce(admin.address) }); + } + console.log("[local-sim] minted mUSD to admin, trader, bot"); + + // Approve Router to spend admin's mUSD (for market creation) + await musd.approve(await router.getAddress(), ethers.MaxUint256, { + nonce: await nextNonce(admin.address), + }); + + // Approve Router for bot signer too + const musdBot = musd.connect(botSigner) as RuntimeContract; + await musdBot.approve(await router.getAddress(), ethers.MaxUint256, { + nonce: await nextNonce(botSigner.address), + }); + + return { + admin, + operator, + reporter, + treasury, + marketMakerFeeSink, + trader, + botSigner, + finalizer, + challenger, + oracle, + clob, + musd, + router, + nextNonce, + }; +} + +// ─── Create Markets ────────────────────────────────────────────────────────── + +async function createMarkets( + contracts: Awaited>, + provider: ethers.JsonRpcProvider, + chain: BettingEvmChain, +) { + const { admin, operator, reporter, oracle, clob, router, nextNonce } = contracts; + const oracleReporter = oracle.connect(reporter) as RuntimeContract; + const clobOperator = clob.connect(operator) as RuntimeContract; + + const duel = duelKey(`local-sim-${chain}`); + const duelId = `${chain}-local-sim`; + const participantA = participantHash("agent-alpha"); + const participantB = participantHash("agent-beta"); + const latestBlock = await provider.getBlock("latest"); + const now = BigInt(latestBlock?.timestamp ?? Math.floor(Date.now() / 1000)); + + // Create CLOB duel + market + console.log("[local-sim] creating CLOB duel + market..."); + await oracleReporter.upsertDuel( + duel, + participantA, + participantB, + now, + now + 600n, // betCloseTs 10 min from now + now + 1200n, + `local://${chain}-local-sim`, + DUEL_STATUS_BETTING_OPEN, + { nonce: await nextNonce(reporter.address) }, + ); + await clobOperator.createMarketForDuel(duel, MARKET_KIND_DUEL_WINNER, { + nonce: await nextNonce(operator.address), + }); + console.log(`[local-sim] CLOB market created for duel ${duel.slice(0, 10)}...`); + + // Create AMM market via Router + console.log("[local-sim] creating AMM market via Router..."); + const collateral = ethers.parseUnits("10000", 18); // 10k mUSD initial liquidity + const duration = 600; // 10 minutes + + const tx = await router.create( + "Local Sim Market", + "Test market for local simulation", + "local://sim", + duel, + false, // static liquidity (simpler) + duration, + collateral, + { nonce: await nextNonce(admin.address) }, + ); + const receipt = await tx.wait(); + + // Extract AMM market address from MarketCreated event + const routerInterface = router.interface; + let ammMarketAddress: string | null = null; + for (const log of receipt.logs) { + try { + const parsed = routerInterface.parseLog({ topics: log.topics as string[], data: log.data }); + if (parsed?.name === "MarketCreated") { + ammMarketAddress = parsed.args.market; + break; + } + } catch {} + } + + if (!ammMarketAddress) { + // Fallback: query getAllMarkets + const allMarkets = await router.getAllMarkets(); + ammMarketAddress = allMarkets[allMarkets.length - 1]; + } + console.log(`[local-sim] AMM market: ${ammMarketAddress}`); + + // Verify AMM market is readable via getMarketDetails() + const lvrMarket = new ethers.Contract(ammMarketAddress!, [ + "function getMarketDetails() view returns (uint8, uint256, uint256, uint256, uint256, uint256, uint256, uint256)", + "function getPriceYes() view returns (uint256)", + "function yesToken() view returns (address)", + "function noToken() view returns (address)", + "function state() view returns (uint8)", + "function isDynamic() view returns (bool)", + ], provider); + + const [state, marketDeadline, outcome, liquidity, reserveYes, reserveNo, priceYes, priceNo] = + await lvrMarket.getMarketDetails(); + + console.log(`[local-sim] AMM state: ${state}, isDynamic: ${await lvrMarket.isDynamic()}`); + console.log(`[local-sim] AMM reserves: yes=${ethers.formatUnits(reserveYes, 18)}, no=${ethers.formatUnits(reserveNo, 18)}`); + console.log(`[local-sim] AMM liquidity: ${ethers.formatUnits(liquidity, 18)}`); + console.log(`[local-sim] AMM priceYes: ${ethers.formatUnits(priceYes, 18)}, priceNo: ${ethers.formatUnits(priceNo, 18)}`); + console.log(`[local-sim] AMM deadline: ${new Date(Number(marketDeadline) * 1000).toISOString()}`); + + return { + duel, + duelId, + ammMarketAddress: ammMarketAddress!, + betCloseTime: Number(now + 600n) * 1000, + }; +} + +// ─── Main ──────────────────────────────────────────────────────────────────── + +async function main() { + const { chain, cycles } = parseArgs(); + let anvil: ChildProcess | null = null; + let stubServer: { close: () => Promise } | null = null; + + try { + // Start anvil + anvil = await startAnvil(); + const provider = new ethers.JsonRpcProvider(ANVIL_RPC_URL); + + // Deploy all contracts + const contracts = await deployContracts(provider, chain); + + // Create CLOB + AMM markets + const { duel, duelId, ammMarketAddress, betCloseTime } = await createMarkets( + contracts, + provider, + chain, + ); + + // Start stub API server + const stubState: StubState = { + duelKey: duel, + duelId, + marketStatus: "OPEN", + phase: "FIGHTING", + betCloseTime, + updatedAt: Date.now(), + hpA: 85, + hpB: 40, + ammMarketAddress, + }; + const stub = await startStubServer(chain, stubState); + stubServer = stub; + + // Configure environment for MM bot + const chainUpper = chain.toUpperCase(); + process.env.MM_ENV = "testnet"; + process.env.EVM_PRIVATE_KEY = contracts.botSigner.privateKey; + process.env.MM_ENABLE_BSC = chain === "bsc" ? "true" : "false"; + process.env.MM_ENABLE_BASE = chain === "base" ? "true" : "false"; + process.env.MM_ENABLE_AVAX = chain === "avax" ? "true" : "false"; + process.env.MM_ENABLE_SOLANA = "false"; + process.env.MM_MARKETS_CACHE_MS = "0"; + process.env.MM_DUEL_SIGNAL_CACHE_MS = "0"; + process.env.MM_DUEL_SIGNAL_FETCH_TIMEOUT_MS = "500"; + process.env.CANCEL_STALE_AGE_MS = "1000"; + process.env.ORDER_SIZE_MIN = "50"; + process.env.ORDER_SIZE_MAX = "100"; + process.env.MM_PREDICTION_MARKETS_API_URL = stub.apiUrl; + process.env.MM_DUEL_STATE_API_URL = stub.duelUrl; + process.env[`EVM_${chainUpper}_RPC_URL`] = ANVIL_RPC_URL; + process.env[`CLOB_CONTRACT_ADDRESS_${chainUpper}`] = await contracts.clob.getAddress(); + process.env[`${chainUpper}_DUEL_ORACLE_ADDRESS`] = await contracts.oracle.getAddress(); + + // AMM env vars + process.env.MM_ENABLE_AMM = "true"; + process.env.MM_ENABLE_AMM_SOLANA = "false"; + process.env[`AMM_ROUTER_ADDRESS_${chainUpper}`] = await contracts.router.getAddress(); + process.env[`MUSD_TOKEN_ADDRESS_${chainUpper}`] = await contracts.musd.getAddress(); + process.env.MM_AMM_DEVIATION_THRESHOLD_BPS = "100"; // Lower threshold for testing + process.env.MM_AMM_MAX_TRADE_SIZE = "100000"; + process.env.MM_AMM_MIN_TRADE_SIZE = "1000"; + process.env.MM_AMM_MAX_POSITION_SIZE = "500000"; + + // Import and create MM bot + const { CrossChainMarketMaker } = await import("./index.ts"); + const mm = new CrossChainMarketMaker({ + stateStore: createTestMarketMakerStateStore(), + }); + + console.log(`\n[local-sim] ═══ Running ${cycles} market-making cycles ═══\n`); + + const config = mm.getConfig(); + console.log("[local-sim] Config:", JSON.stringify({ + chain, + clobEnabled: (config as any)[`${chain}Enabled`], + ammEnabled: config.ammEnabled, + ammEvmChains: config.ammEvmChains, + }, null, 2)); + + for (let i = 0; i < cycles; i++) { + console.log(`\n[local-sim] ─── Cycle ${i + 1}/${cycles} ───`); + + // Vary HP signal to create fair value changes → trigger AMM trades + stubState.hpA = Math.max(10, Math.min(95, 85 - i * 5 + Math.floor(Math.random() * 10))); + stubState.hpB = Math.max(10, Math.min(95, 40 + i * 3 + Math.floor(Math.random() * 10))); + stubState.updatedAt = Date.now(); + + try { + await mm.marketMakeCycle(); + } catch (cycleErr: any) { + console.warn(`[local-sim] cycle error (non-fatal): ${cycleErr.message?.slice(0, 120)}`); + } + + const activeOrders = mm.getActiveOrders().filter((o: any) => o.chainKey === chain); + const ammPositions = mm.getAmmPositions(); + const inventory = mm.getInventory(); + + console.log(`[local-sim] HP: A=${stubState.hpA}, B=${stubState.hpB}`); + console.log(`[local-sim] CLOB orders: ${activeOrders.length}`); + if (activeOrders.length > 0) { + for (const order of activeOrders) { + console.log(` ${order.side === SELL_SIDE ? "ASK" : "BID"} price=${order.price} amount=${order.amount}`); + } + } + console.log(`[local-sim] AMM positions: ${ammPositions.length}`); + for (const pos of ammPositions) { + console.log(` ${pos.chainKey} yes=${pos.yesBalance} no=${pos.noBalance} cost=${pos.costBasis}`); + } + console.log(`[local-sim] Inventory: yes=${inventory.yes}, no=${inventory.no}, ammYes=${inventory.ammYes}, ammNo=${inventory.ammNo}`); + + await sleep(200); + } + + // Read on-chain AMM state after trading + const lvrMarket = new ethers.Contract(ammMarketAddress, [ + "function getMarketDetails() view returns (uint8, uint256, uint256, uint256, uint256, uint256, uint256, uint256)", + ], provider); + + const [, , , finalLiquidity, finalReserveYes, finalReserveNo] = + await lvrMarket.getMarketDetails(); + + console.log(`\n[local-sim] ═══ Final State ═══`); + console.log(`[local-sim] AMM reserves: yes=${ethers.formatUnits(finalReserveYes, 18)}, no=${ethers.formatUnits(finalReserveNo, 18)}`); + console.log(`[local-sim] AMM liquidity: ${ethers.formatUnits(finalLiquidity, 18)}`); + + const finalConfig = mm.getConfig(); + const finalInventory = mm.getInventory(); + const finalOrders = mm.getActiveOrders(); + const finalAmm = mm.getAmmPositions(); + + console.log( + JSON.stringify( + { + ok: true, + chain, + cycles, + duel: duel.slice(0, 18) + "...", + ammMarket: ammMarketAddress, + clobOrders: finalOrders.length, + ammPositions: finalAmm.length, + inventory: finalInventory, + ammFinalReserves: { + yes: ethers.formatUnits(finalReserveYes, 18), + no: ethers.formatUnits(finalReserveNo, 18), + }, + config: { + ammEnabled: finalConfig.ammEnabled, + ammEvmChains: finalConfig.ammEvmChains, + }, + }, + null, + 2, + ), + ); + } finally { + if (stubServer) await stubServer.close(); + if (anvil) { + anvil.kill(); + console.log("[local-sim] anvil stopped"); + } + } +} + +main().catch((error) => { + console.error(`[local-sim] fatal: ${(error as Error).message}`); + console.error((error as Error).stack); + process.exit(1); +}); diff --git a/packages/market-maker-bot/src/simulate.ts b/packages/market-maker-bot/src/simulate.ts index e0f67567..0992959f 100644 --- a/packages/market-maker-bot/src/simulate.ts +++ b/packages/market-maker-bot/src/simulate.ts @@ -12,6 +12,14 @@ function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } +type SimMode = "clob" | "amm" | "both"; + +function parseSimMode(): SimMode { + const raw = (process.env.SIM_MODE ?? "both").toLowerCase(); + if (raw === "clob" || raw === "amm" || raw === "both") return raw; + return "both"; +} + function bootstrapDefaults() { if (!process.env.EVM_PRIVATE_KEY) { process.env.EVM_PRIVATE_KEY = DEFAULT_DEV_PRIVATE_KEY; @@ -28,6 +36,14 @@ function bootstrapDefaults() { if (!process.env.SOLANA_RPC_URL) { process.env.SOLANA_RPC_URL = "http://127.0.0.1:8899"; } + + const simMode = parseSimMode(); + if (simMode === "clob") { + process.env.MM_ENABLE_AMM = "false"; + } else if (simMode === "amm") { + process.env.MM_ENABLE_AMM = "true"; + } + // "both" leaves MM_ENABLE_AMM at its default (true) } async function main() { @@ -47,14 +63,17 @@ async function main() { await sleep(delayMs); } + const simMode = parseSimMode(); const config = mm.getConfig(); const inventory = mm.getInventory(); const activeOrders = mm.getActiveOrders(); + const ammPositions = mm.getAmmPositions(); console.log("[simulate] Completed."); console.log( JSON.stringify( { + simMode, cycles, chainStatus: { bsc: config.bscEnabled, @@ -62,7 +81,11 @@ async function main() { avax: config.avaxEnabled, solana: config.solanaEnabled, }, + ammEnabled: config.ammEnabled, + ammSolanaEnabled: config.ammSolanaEnabled, + ammEvmChains: config.ammEvmChains, inventory, + ammPositions, activeOrderCount: activeOrders.length, }, null, @@ -70,12 +93,18 @@ async function main() { ), ); - if ( - !config.bscEnabled && - !config.baseEnabled && - !config.avaxEnabled && - !config.solanaEnabled - ) { + const hasClobChain = + config.bscEnabled || config.baseEnabled || config.avaxEnabled || config.solanaEnabled; + const hasAmmChain = + config.ammEnabled && (config.ammSolanaEnabled || Object.values(config.ammEvmChains ?? {}).some(Boolean)); + + if (simMode === "clob" && !hasClobChain) { + throw new Error("No CLOB chain endpoints were reachable"); + } + if (simMode === "amm" && !hasAmmChain) { + throw new Error("No AMM chain endpoints were reachable"); + } + if (simMode === "both" && !hasClobChain && !hasAmmChain) { throw new Error("No chain endpoints were reachable"); } } diff --git a/packages/market-maker-bot/src/solana-helpers.ts b/packages/market-maker-bot/src/solana-helpers.ts index ad2f0ee0..0ef1e812 100644 --- a/packages/market-maker-bot/src/solana-helpers.ts +++ b/packages/market-maker-bot/src/solana-helpers.ts @@ -95,3 +95,58 @@ export function findPriceLevelPda( marketProgramId, )[0]; } + +// --- AMM (lvr_amm) PDA helpers --- + +function betIdToBytes(betId: bigint): Buffer { + const buf = Buffer.alloc(8); + buf.writeBigUInt64LE(betId); + return buf; +} + +export function findAmmConfigPda(ammProgramId: PublicKey): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("amm_config")], + ammProgramId, + )[0]; +} + +export function findAmmAdminStatePda(ammProgramId: PublicKey): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("admin_state")], + ammProgramId, + )[0]; +} + +export function findAmmBetPda( + ammProgramId: PublicKey, + betId: bigint, + creator: PublicKey, +): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("bet"), betIdToBytes(betId), creator.toBuffer()], + ammProgramId, + )[0]; +} + +export function findAmmMintYesPda( + ammProgramId: PublicKey, + betId: bigint, + creator: PublicKey, +): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("mint_yes"), betIdToBytes(betId), creator.toBuffer()], + ammProgramId, + )[0]; +} + +export function findAmmMintNoPda( + ammProgramId: PublicKey, + betId: bigint, + creator: PublicKey, +): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("mint_no"), betIdToBytes(betId), creator.toBuffer()], + ammProgramId, + )[0]; +} diff --git a/packages/market-maker-bot/src/storage/index.ts b/packages/market-maker-bot/src/storage/index.ts index cf2eb906..af3bf19e 100644 --- a/packages/market-maker-bot/src/storage/index.ts +++ b/packages/market-maker-bot/src/storage/index.ts @@ -3,6 +3,7 @@ import { createPostgresMarketMakerStateStore } from "./postgres.ts"; export { createInMemoryMarketMakerStateStore } from "./memory.ts"; export type { + AmmPositionRecord, ClaimBacklogItem, ClaimBacklogInput, ManagedOrderStatus, diff --git a/packages/market-maker-bot/src/storage/memory.ts b/packages/market-maker-bot/src/storage/memory.ts index 7b74e151..c738d271 100644 --- a/packages/market-maker-bot/src/storage/memory.ts +++ b/packages/market-maker-bot/src/storage/memory.ts @@ -1,4 +1,5 @@ import type { + AmmPositionRecord, ClaimBacklogInput, ClaimBacklogItem, MarketMakerStateStore, @@ -15,6 +16,7 @@ export class InMemoryMarketMakerStateStore implements MarketMakerStateStore { private readonly claimBacklog = new Map(); private readonly outbox = new Map(); private readonly cursors = new Map(); + private readonly ammPositions = new Map(); private nextOutboxId = 1; private nextEventId = 1; @@ -242,6 +244,14 @@ export class InMemoryMarketMakerStateStore implements MarketMakerStateStore { updatedAt, }); } + + async listAmmPositions(): Promise { + return [...this.ammPositions.values()]; + } + + async upsertAmmPosition(record: AmmPositionRecord): Promise { + this.ammPositions.set(record.positionKey, structuredClone(record)); + } } export function createInMemoryMarketMakerStateStore() { diff --git a/packages/market-maker-bot/src/storage/postgres.ts b/packages/market-maker-bot/src/storage/postgres.ts index 648f8a54..47851e2e 100644 --- a/packages/market-maker-bot/src/storage/postgres.ts +++ b/packages/market-maker-bot/src/storage/postgres.ts @@ -1,6 +1,7 @@ import { createRequire } from "node:module"; import type { + AmmPositionRecord, ClaimBacklogInput, ClaimBacklogItem, MarketMakerStateStore, @@ -81,6 +82,18 @@ CREATE TABLE IF NOT EXISTS outbox ( ); ALTER TABLE outbox ADD COLUMN IF NOT EXISTS lease_owner TEXT; ALTER TABLE outbox ADD COLUMN IF NOT EXISTS lease_expires_at BIGINT; +CREATE TABLE IF NOT EXISTS amm_positions ( + position_key TEXT PRIMARY KEY, + chain_key TEXT NOT NULL, + market_ref TEXT NOT NULL, + bet_id TEXT NOT NULL, + creator TEXT NOT NULL, + yes_balance TEXT NOT NULL DEFAULT '0', + no_balance TEXT NOT NULL DEFAULT '0', + cost_basis TEXT NOT NULL DEFAULT '0', + settled BOOLEAN NOT NULL DEFAULT FALSE, + updated_at BIGINT NOT NULL +); `; function parseOrderRecord(row: Record): OrderRecord { @@ -528,6 +541,51 @@ export class PostgresMarketMakerStateStore implements MarketMakerStateStore { [cursorKey, cursorValue, updatedAt], ); } + + async listAmmPositions(): Promise { + const result = await this.pool.query( + `SELECT * FROM amm_positions ORDER BY updated_at DESC`, + ); + return result.rows.map((row: Record) => ({ + positionKey: row.position_key, + chainKey: row.chain_key, + marketRef: row.market_ref, + betId: row.bet_id, + creator: row.creator, + yesBalance: row.yes_balance, + noBalance: row.no_balance, + costBasis: row.cost_basis, + settled: row.settled, + updatedAt: Number(row.updated_at), + })); + } + + async upsertAmmPosition(record: AmmPositionRecord): Promise { + await this.pool.query( + `INSERT INTO amm_positions ( + position_key, chain_key, market_ref, bet_id, creator, + yes_balance, no_balance, cost_basis, settled, updated_at + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) + ON CONFLICT (position_key) DO UPDATE SET + yes_balance = EXCLUDED.yes_balance, + no_balance = EXCLUDED.no_balance, + cost_basis = EXCLUDED.cost_basis, + settled = EXCLUDED.settled, + updated_at = EXCLUDED.updated_at`, + [ + record.positionKey, + record.chainKey, + record.marketRef, + record.betId, + record.creator, + record.yesBalance, + record.noBalance, + record.costBasis, + record.settled, + record.updatedAt, + ], + ); + } } export function createPostgresMarketMakerStateStore(connectionString: string) { diff --git a/packages/market-maker-bot/src/storage/types.ts b/packages/market-maker-bot/src/storage/types.ts index f41e2cf4..bd7ee6f6 100644 --- a/packages/market-maker-bot/src/storage/types.ts +++ b/packages/market-maker-bot/src/storage/types.ts @@ -110,6 +110,19 @@ export type OutboxInput = Omit< lastError?: string | null; }; +export type AmmPositionRecord = { + positionKey: string; + chainKey: string; + marketRef: string; + betId: string; + creator: string; + yesBalance: string; + noBalance: string; + costBasis: string; + settled: boolean; + updatedAt: number; +}; + export type MarketMakerStateStore = { ensureReady(): Promise; close(): Promise; @@ -152,4 +165,6 @@ export type MarketMakerStateStore = { failOutbox(id: number, lastError: string, availableAt: number): Promise; getCursor(cursorKey: string): Promise; setCursor(cursorKey: string, cursorValue: string, updatedAt?: number): Promise; + listAmmPositions(): Promise; + upsertAmmPosition(record: AmmPositionRecord): Promise; }; diff --git a/packages/simulation-dashboard/src/server.ts b/packages/simulation-dashboard/src/server.ts index a36c4b25..5228ca83 100644 --- a/packages/simulation-dashboard/src/server.ts +++ b/packages/simulation-dashboard/src/server.ts @@ -214,8 +214,14 @@ const ATTACKER_STRATEGIES = new Set([ "stress_test", "cancel_replace", ]); -const MARKET_STATUS_RESOLVED = 3; -const MARKET_STATUS_CANCELLED = 4; +// GoldClob (CLOB) enum: NULL=0, OPEN=1, LOCKED=2, RESOLVED=3, CANCELLED=4 +// LvrMarket (AMM) enum: OPEN=0, CLOSED=1, PENDING=2, DISPUTED=3, RESOLVED=4 +const CLOB_STATUS = { RESOLVED: 3, CANCELLED: 4 } as const; +const AMM_STATUS = { RESOLVED: 4, CANCELLED: undefined } as const; + +// Default to CLOB for current sim (anvil runs GoldClob) +const MARKET_STATUS_RESOLVED = CLOB_STATUS.RESOLVED; +const MARKET_STATUS_CANCELLED = CLOB_STATUS.CANCELLED; let peakInventorySeen = 0; let worstMarketMakerPnl = 0; let bestAttackerPnlSeen = 0; @@ -230,6 +236,124 @@ let closeGuardTripsSeen = 0; let circuitBreakerTripsSeen = 0; let scenarioMarketLocked = false; let lastComputedState: Record | null = null; + +// ─── Game API compatibility (SSE + HTTP for betting frontend) ──────────────── +const sseClients = new Set(); +let simStartedAtMs = Date.now(); +let duelOpenedAtMs = Date.now(); +let lastStreamingState: Record | null = null; + +function buildStreamingStateUpdate(): Record { + const state = lastComputedState; + const now = Date.now(); + const marketStatus = state?.market?.status ?? 0; + + // Map sim market status to streaming phase + let phase: string; + if (!state || marketStatus === 0) { + phase = "IDLE"; + } else if (marketStatus === MARKET_STATUS_RESOLVED || marketStatus === MARKET_STATUS_CANCELLED) { + phase = "RESOLUTION"; + } else { + phase = "FIGHTING"; + } + + // Synthesize agent HP from sim tick progress + const tickProgress = Math.min(1, simTick / Math.max(1, 200)); // ~200 ticks typical scenario + const winner = state?.market?.winner ?? 0; + const isResolved = marketStatus === MARKET_STATUS_RESOLVED || marketStatus === MARKET_STATUS_CANCELLED; + let hp1 = 100; + let hp2 = 100; + if (isResolved) { + hp1 = winner === 1 ? Math.max(10, Math.round(100 - tickProgress * 40)) : 0; + hp2 = winner === 2 ? Math.max(10, Math.round(100 - tickProgress * 40)) : 0; + if (winner === 0) { hp1 = 0; hp2 = 0; } // cancelled + } else if (simRunning) { + // Both lose HP proportional to progress, leader stays ahead + const bestBid = state?.market?.bestBid ?? 500; + const edge = (bestBid - 500) / 500; // positive = agent1 favored + hp1 = Math.max(5, Math.round(100 - tickProgress * (40 - edge * 20))); + hp2 = Math.max(5, Math.round(100 - tickProgress * (40 + edge * 20))); + } + + const label = currentDuelLabel || "sim-duel-0"; + const parts = label.split("-"); + const duelId = `sim-${duelCounter}`; + const betCloseMs = duelOpenedAtMs + 604800 * 1000; // matches the 1-week window + + const update = { + type: "STREAMING_STATE_UPDATE", + cycle: { + cycleId: duelId, + phase, + cycleStartTime: simStartedAtMs, + phaseStartTime: duelOpenedAtMs, + phaseEndTime: betCloseMs, + timeRemaining: Math.max(0, Math.round((betCloseMs - now) / 1000)), + agent1: { + id: "agent-alpha", + name: "Agent Alpha", + provider: "Simulation", + model: "v1", + hp: hp1, + maxHp: 100, + combatLevel: 1, + wins: 0, + losses: 0, + damageDealtThisFight: 100 - hp2, + }, + agent2: { + id: "agent-beta", + name: "Agent Beta", + provider: "Simulation", + model: "v1", + hp: hp2, + maxHp: 100, + combatLevel: 1, + wins: 0, + losses: 0, + damageDealtThisFight: 100 - hp1, + }, + duelId, + duelKeyHex: currentDuelKey ? currentDuelKey.replace(/^0x/, "") : null, + betOpenTime: duelOpenedAtMs, + betCloseTime: betCloseMs, + fightStartTime: duelOpenedAtMs, + duelEndTime: isResolved ? now : null, + winnerId: isResolved && winner === 1 ? "agent-alpha" : isResolved && winner === 2 ? "agent-beta" : null, + winnerName: isResolved && winner === 1 ? "Agent Alpha" : isResolved && winner === 2 ? "Agent Beta" : null, + winReason: isResolved ? "simulation" : null, + countdown: null, + seed: null, + replayHash: null, + }, + leaderboard: [], + cameraTarget: null, + seq: simTick, + emittedAt: now, + }; + lastStreamingState = update; + return update; +} + +function broadcastSse(): void { + if (sseClients.size === 0) return; + const update = buildStreamingStateUpdate(); + const frame = `event: state\ndata: ${JSON.stringify(update)}\n\n`; + for (const res of sseClients) { + try { + res.write(frame); + } catch { + sseClients.delete(res); + } + } +} + +function writeCorsHeaders(res: ServerResponse): void { + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); + res.setHeader("Access-Control-Allow-Headers", "Content-Type, Cache-Control, Last-Event-ID"); +} let lastObservedMarketState: CachedMarketState | null = null; let lastObservedProtocolMmBalance: bigint | null = null; let lastObservedRuntimeMmBalance: bigint | null = null; @@ -1430,6 +1554,7 @@ async function openNewDuel(): Promise { currentDuelLabel = `sim-duel-${duelCounter}`; currentDuelKey = duelKey(currentDuelLabel); currentScenarioId = "manual"; + duelOpenedAtMs = Date.now(); resetScenarioMetrics(); const reporter = reporterSigner ?? (await provider.getSigner(2)); @@ -3267,6 +3392,8 @@ function broadcast(msg: any): void { ws.send(payload); } } + // Also push to SSE clients for the betting frontend + broadcastSse(); } function handleWsMessage(data: string): void { @@ -3400,6 +3527,7 @@ function writeJson( statusCode: number, payload: unknown, ): void { + writeCorsHeaders(res); res.writeHead(statusCode, { "Content-Type": "application/json", "Cache-Control": "no-cache", @@ -3416,6 +3544,119 @@ async function handleHttpRequest( `http://${req.headers.host ?? `127.0.0.1:${HTTP_PORT}`}`, ); + // ─── CORS preflight ────────────────────────────────────────────────────── + if (req.method === "OPTIONS") { + writeCorsHeaders(res); + res.writeHead(204); + res.end(); + return; + } + + // ─── Game API compatibility endpoints (for betting frontend) ───────────── + + if (requestUrl.pathname === "/api/config") { + writeJson(res, 200, { + chainId: 31337, + rpcUrl: `http://127.0.0.1:${ANVIL_PORT}`, + clobAddress: clobAddr, + oracleAddress: oracleAddr, + duelKey: currentDuelKey, + duelLabel: currentDuelLabel, + marketKey: currentMarketKey, + }); + return; + } + + if (requestUrl.pathname === "/api/streaming/state/events") { + writeCorsHeaders(res); + res.writeHead(200, { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive", + }); + // Send current state immediately + const current = buildStreamingStateUpdate(); + res.write(`event: state\ndata: ${JSON.stringify(current)}\n\n`); + sseClients.add(res); + req.on("close", () => { + sseClients.delete(res); + }); + return; + } + + if (requestUrl.pathname === "/api/streaming/state") { + const state = lastStreamingState ?? buildStreamingStateUpdate(); + writeJson(res, 200, state); + return; + } + + if (requestUrl.pathname === "/api/streaming/duel-context") { + const ss = lastStreamingState ?? buildStreamingStateUpdate(); + const cycle = ss.cycle ?? {}; + // useDuelContext expects { type, cycle: {...}, leaderboard, cameraTarget } + writeJson(res, 200, { + type: "STREAMING_DUEL_CONTEXT", + cycle: { + ...cycle, + agent1: cycle.agent1 ? { ...cycle.agent1, inventory: [], monologues: [] } : null, + agent2: cycle.agent2 ? { ...cycle.agent2, inventory: [], monologues: [] } : null, + }, + leaderboard: ss.leaderboard ?? [], + cameraTarget: ss.cameraTarget ?? null, + }); + return; + } + + if (requestUrl.pathname === "/api/arena/prediction-markets/active") { + const now = Date.now(); + const ss = lastStreamingState ?? buildStreamingStateUpdate(); + const cycle = ss.cycle ?? {}; + const marketStatus = lastComputedState?.market?.status ?? 0; + const isResolved = marketStatus === MARKET_STATUS_RESOLVED || marketStatus === MARKET_STATUS_CANCELLED; + const winner = lastComputedState?.market?.winner ?? 0; + + let lifecycleStatus = "IDLE"; + if (marketStatus === 1) lifecycleStatus = "OPEN"; + else if (marketStatus === 2) lifecycleStatus = "LOCKED"; + else if (marketStatus === MARKET_STATUS_RESOLVED) lifecycleStatus = "RESOLVED"; + else if (marketStatus === MARKET_STATUS_CANCELLED) lifecycleStatus = "CANCELLED"; + + let winnerStr = "NONE"; + if (isResolved && winner === 1) winnerStr = "A"; + else if (isResolved && winner === 2) winnerStr = "B"; + + writeJson(res, 200, { + duel: { + duelKey: currentDuelKey || null, + duelId: cycle.duelId ?? `sim-${duelCounter}`, + phase: cycle.phase ?? "IDLE", + winner: isResolved ? winnerStr : null, + betCloseTime: cycle.betCloseTime ?? null, + }, + markets: [ + { + chainKey: "bsc", + duelKey: currentDuelKey || null, + duelId: cycle.duelId ?? `sim-${duelCounter}`, + marketId: `sim-bsc-${duelCounter}`, + marketRef: currentMarketKey || null, + lifecycleStatus, + winner: winnerStr, + betCloseTime: cycle.betCloseTime ?? null, + contractAddress: clobAddr, + programId: null, + txRef: null, + syncedAt: now, + marketType: "clob", + }, + ], + updatedAt: now, + }); + return; + } + + // ─── Original sim dashboard API endpoints ──────────────────────────────── + if (requestUrl.pathname === "/api/state") { writeJson(res, 200, { ok: true, diff --git a/scripts/ci-gate-solana-build.ts b/scripts/ci-gate-solana-build.ts index be693371..0abf59ee 100644 --- a/scripts/ci-gate-solana-build.ts +++ b/scripts/ci-gate-solana-build.ts @@ -16,6 +16,12 @@ const trackedArtifactPaths = [ "packages/hyperbet-solana/anchor/target/idl", "packages/hyperbet-solana/app/src/idl", "packages/hyperbet-solana/keeper/src/idl", + "packages/hyperbet-ui/src/idl", + "packages/hyperbet-bsc/app/src/idl", + "packages/hyperbet-bsc/keeper/src/idl", + "packages/hyperbet-avax/keeper/src/idl", + "packages/hyperbet-evm/keeper/src/idl", + "packages/market-maker-bot/src/idl", ]; function currentGitStatus(paths: string[]): string { diff --git a/scripts/sim-frontend.sh b/scripts/sim-frontend.sh new file mode 100755 index 00000000..64aa0d17 --- /dev/null +++ b/scripts/sim-frontend.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Start simulation dashboard + betting frontend together. +# The sim dashboard acts as the Game API server for the frontend. + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +SIM_PID="" +cleanup() { + if [[ -n "$SIM_PID" ]]; then + kill "$SIM_PID" 2>/dev/null || true + fi +} +trap cleanup EXIT + +echo "==> Starting simulation dashboard..." +cd "$ROOT_DIR" +bun run --cwd packages/simulation-dashboard dev & +SIM_PID=$! + +echo "==> Waiting for sim dashboard to be ready on :3401..." +for i in $(seq 1 60); do + if curl -sf http://localhost:3401/api/config > /dev/null 2>&1; then + break + fi + if ! kill -0 "$SIM_PID" 2>/dev/null; then + echo "ERROR: Simulation dashboard crashed during startup" + exit 1 + fi + sleep 1 +done + +if ! curl -sf http://localhost:3401/api/config > /dev/null 2>&1; then + echo "ERROR: Simulation dashboard did not become ready in 60s" + exit 1 +fi + +echo "==> Fetching contract addresses from sim..." +CONFIG=$(curl -sf http://localhost:3401/api/config) +CLOB=$(echo "$CONFIG" | jq -r .clobAddress) +ORACLE=$(echo "$CONFIG" | jq -r .oracleAddress) +DUEL_KEY=$(echo "$CONFIG" | jq -r .duelKey) + +echo " CLOB: $CLOB" +echo " Oracle: $ORACLE" +echo " Duel: $DUEL_KEY" + +# Write .env.local for the EVM betting frontend +ENV_FILE="$ROOT_DIR/packages/hyperbet-evm/app/.env.local" +cat > "$ENV_FILE" << EOF +VITE_GAME_API_URL=http://localhost:3401 +VITE_BSC_RPC_URL=http://localhost:18546 +VITE_BSC_CHAIN_ID=31337 +VITE_BSC_GOLD_CLOB_ADDRESS=$CLOB +EOF + +echo "==> Wrote $ENV_FILE" +echo "==> Starting betting frontend dev server..." +cd "$ROOT_DIR" +exec bun run --cwd packages/hyperbet-evm/app dev