ido more fixes
This commit is contained in:
parent
aa99f775da
commit
3f8a9cd026
2 changed files with 116 additions and 70 deletions
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(non_snake_case)]
|
||||
use anyhow::Result;
|
||||
use log::{info};
|
||||
use log::{info,warn};
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_traits::{Zero, ToPrimitive};
|
||||
use bitcoincash::blockdata::script::{Builder, Script, Instruction};
|
||||
|
|
@ -360,7 +360,7 @@ fn build_partial_postlaunch_bytecode(permanentLiquidityShare: &BigInt, price: &B
|
|||
bytecode
|
||||
}
|
||||
|
||||
fn build_partial_ido_initaitor_bytecode(postLaunchPartialBytecode: &[u8], permanentPoolOTokenReserveOutpointIndex: &BigInt, offeringInitiatorOutpointIndex: &BigInt) -> Vec<u8> {
|
||||
fn build_partial_ido_initiator_bytecode(postLaunchPartialBytecode: &[u8], permanentPoolOTokenReserveOutpointIndex: &BigInt, offeringInitiatorOutpointIndex: &BigInt) -> Vec<u8> {
|
||||
let mut bytecode = Builder::new()
|
||||
.push_slice(postLaunchPartialBytecode)
|
||||
.push_slice(&STORAGE_CONTRACT)
|
||||
|
|
@ -840,6 +840,9 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
|
|||
// params main
|
||||
match &instructions[1] {
|
||||
Ok(Instruction::PushBytes(data)) => {
|
||||
if data.len() < 185 {
|
||||
return Err(anyhow::anyhow!("Incorrect announcement.mainData size"));
|
||||
}
|
||||
preinit_parameters = IdoPreInitParameters {
|
||||
authguardLockingBytecode: authguardLockingBytecode,
|
||||
offering: IdoParametersOffering {
|
||||
|
|
@ -914,7 +917,7 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
|
|||
// find authguardCategory
|
||||
let mut authguardNftOut = None;
|
||||
if preinit_parameters.authguardNftOutputIndex >= BigInt::from(0) {
|
||||
authguardNftOut = tx.output.get(preinit_parameters.authguardNftOutputIndex.to_usize().unwrap());
|
||||
authguardNftOut = tx.output.get(preinit_parameters.authguardNftOutputIndex.to_usize().ok_or_else(|| anyhow::anyhow!("authguardNftOutputIndex out of range"))?);
|
||||
}
|
||||
|
||||
let preInit_lock_parameters = IdoPreInitLockParameters {
|
||||
|
|
@ -1031,7 +1034,7 @@ async fn create_ido_context_from_preinit(network: Option<Network>, tx: &Transact
|
|||
if build_p2sh32_script(
|
||||
&build_storage_script_with_data(
|
||||
1,
|
||||
&build_partial_ido_initaitor_bytecode(
|
||||
&build_partial_ido_initiator_bytecode(
|
||||
&build_partial_postlaunch_bytecode(
|
||||
&preinit_parameters.permanentLiquidityShareNumerator,
|
||||
&preinit_parameters.offering.offer.priceNumerator,
|
||||
|
|
@ -1108,7 +1111,7 @@ async fn on_create_ido(
|
|||
let mut dbtx = pool.begin().await?;
|
||||
let result = sqlx::query(
|
||||
"INSERT INTO ido (preinit_txid, init_txid, launch_txid, offering_token_id, offered_token_id, status, parameters, state, is_valid, is_token_created_at_preinit, txchain_entrypoint, txchain_head)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
)
|
||||
.bind(context.preinit_txid)
|
||||
.bind(context.init_txid)
|
||||
|
|
@ -1153,8 +1156,8 @@ async fn on_create_ido(
|
|||
fn is_preinit_state_ready_to_init(state: &IdoPreInitState) -> bool {
|
||||
state.oTokenGenerated != BigInt::from(0) &&
|
||||
state.nextTxSetterFlag == BigInt::from(0) &&
|
||||
vm_number_to_bigint(&state.authguardCategory) != BigInt::from(0) &&
|
||||
vm_number_to_bigint(&state.idoCategory) != BigInt::from(0)
|
||||
state.authguardCategory.iter().any(|&b| b != 0) &&
|
||||
state.idoCategory.iter().any(|&b| b != 0)
|
||||
}
|
||||
|
||||
fn parse_preinit_state_from_tx(
|
||||
|
|
@ -1250,11 +1253,14 @@ fn ido_add_tx(
|
|||
// init outputs created & init tx
|
||||
updates.push(IdoUpdate::Status("ACTIVE".to_string()));
|
||||
updates.push(IdoUpdate::InitTxId(tx.txid().to_blob()));
|
||||
let launcherBytecodeIn = tx.input.get(2).expect("launcher bytecode storage does not exist!");
|
||||
let launcher_data = extract_data_from_unlocking_bytecode_of_storage_with_data(launcherBytecodeIn.script_sig.clone()).expect("failed to extract launcher bytecode");
|
||||
let launcherBytecodeIn = tx.input.get(2).ok_or_else(|| anyhow::anyhow!("launcher bytecode storage does not exist!"))?;
|
||||
let launcher_data = extract_data_from_unlocking_bytecode_of_storage_with_data(launcherBytecodeIn.script_sig.clone()).map_err(|e| anyhow::anyhow!("failed to extract launcher bytecode: {e}"))?;
|
||||
let launcher_script = Script::from(launcher_data);
|
||||
let launcher_inst_list: Vec<_> = launcher_script.instructions().collect();
|
||||
let collectorNFTH: Vec<u8>;
|
||||
if launcher_inst_list.len() == 0 {
|
||||
return Err(anyhow::anyhow!("empty launcher bytecode!"));
|
||||
}
|
||||
match &launcher_inst_list[0] {
|
||||
Ok(Instruction::PushBytes(data)) => {
|
||||
collectorNFTH = data.to_vec();
|
||||
|
|
@ -1277,9 +1283,12 @@ fn ido_add_tx(
|
|||
updates.push(IdoUpdate::State(IdoState::Active(IdoActiveState {
|
||||
counter: BigInt::from(0)
|
||||
})));
|
||||
let tokenStorageOut = tx.output.get(2).expect("token storage does not exist!");
|
||||
let tokenStorageOut = tx.output.get(2).ok_or_else(|| anyhow::anyhow!("token storage does not exist!"))?;
|
||||
let offeringOut = tx.output.get(1).ok_or_else(|| anyhow::anyhow!("offering does not exist!"))?;
|
||||
if tokenStorageOut.token.is_none() || offeringOut.token.is_none() {
|
||||
return Err(anyhow::anyhow!("output#1 & output#2 should have token!"));
|
||||
}
|
||||
updates.push(IdoUpdate::OfferedTokenId(tokenStorageOut.token.as_ref().unwrap().id.to_blob()));
|
||||
let offeringOut = tx.output.get(1).expect("offering does not exist!");
|
||||
updates.push(IdoUpdate::OfferingTokenId(offeringOut.token.as_ref().unwrap().id.to_blob()));
|
||||
return Ok(IdoAddResult {
|
||||
updates: updates,
|
||||
|
|
@ -1303,12 +1312,15 @@ fn ido_add_tx(
|
|||
},
|
||||
"ACTIVE" => {
|
||||
// output#0 should contain a token with offering_token_id
|
||||
let first_output = tx.output.get(0).expect("Should have first output!");
|
||||
let first_output = tx.output.get(0).ok_or_else(|| anyhow::anyhow!("Should have first output!"))?;
|
||||
if first_output.token.is_none() ||
|
||||
first_output.token.as_ref().unwrap().id.to_blob() != context.offering_token_id.clone().unwrap_or_default() ||
|
||||
!first_output.token.as_ref().unwrap().has_nft() {
|
||||
return Err(anyhow::anyhow!("output#0 is not one of the offering nft!"));
|
||||
}
|
||||
if first_output.token.as_ref().unwrap().commitment.len() == 0 {
|
||||
return Err(anyhow::anyhow!("Incorrect commitment size at output#0, should be greater than zero"));
|
||||
}
|
||||
if first_output.token.as_ref().unwrap().commitment[0] & ITEM_TYPE_BITS == ITEM_TYPE_OFFERING {
|
||||
// enforce limitation (xToken == NATIVE_BCH)
|
||||
if let IdoParameters::Active(ref active_params) = context.parameters {
|
||||
|
|
@ -1316,7 +1328,7 @@ fn ido_add_tx(
|
|||
return Err(anyhow::anyhow!("non-null xTokenCategory is not supported"));
|
||||
}
|
||||
}
|
||||
let second_output = tx.output.get(1).expect("Should have the second output!");
|
||||
let second_output = tx.output.get(1).ok_or_else(|| anyhow::anyhow!("Should have the second output!"))?;
|
||||
if second_output.token.is_none() ||
|
||||
second_output.token.as_ref().unwrap().id.to_blob() != context.offering_token_id.clone().unwrap_or_default() ||
|
||||
!second_output.token.as_ref().unwrap().has_nft() {
|
||||
|
|
@ -1325,13 +1337,23 @@ fn ido_add_tx(
|
|||
// input#0 is the offering, add entry
|
||||
// pull owner_nfthash from unlocking bytecode of input#0
|
||||
let owner_nfthash;
|
||||
let instructions: Vec<_> = tx.input.get(0).expect("Should have first input!").script_sig.instructions().collect();
|
||||
let first_input = tx.input.get(0).ok_or_else(|| anyhow::anyhow!("Should have first input!"))?;
|
||||
let instructions: Vec<_> = first_input.script_sig.instructions().collect();
|
||||
if instructions.len() == 0 {
|
||||
return Err(anyhow::anyhow!("empty unlocking bytecode!"));
|
||||
}
|
||||
match &instructions[0] {
|
||||
Ok(Instruction::PushBytes(data)) => {
|
||||
owner_nfthash = data.to_vec();
|
||||
},
|
||||
_ => return Err(anyhow::anyhow!("OP_PUSH expected in the unlocking bytecode of the offering utxo!")),
|
||||
}
|
||||
if first_output.token.as_ref().unwrap().commitment.len() < 9 {
|
||||
return Err(anyhow::anyhow!("Incorrect commitment size at output#0"));
|
||||
}
|
||||
if second_output.token.as_ref().unwrap().commitment.len() < 15 {
|
||||
return Err(anyhow::anyhow!("Incorrect commitment size at output#1"));
|
||||
}
|
||||
updates.push(IdoUpdate::Entry(IdoUpdateEntry {
|
||||
txid: tx.txid().to_blob(),
|
||||
owner_nfthash: owner_nfthash,
|
||||
|
|
@ -1349,6 +1371,9 @@ fn ido_add_tx(
|
|||
// input#0 is the launcher
|
||||
// output#0 distributor
|
||||
let dist_commitment = first_output.token.as_ref().unwrap().commitment.clone();
|
||||
if dist_commitment.len() < 35 {
|
||||
return Err(anyhow::anyhow!("Incorrect commitment size at output#0"));
|
||||
}
|
||||
updates.push(IdoUpdate::Status("DISTRIBUTING".to_string()));
|
||||
updates.push(IdoUpdate::LaunchTxId(tx.txid().to_blob()));
|
||||
updates.push(IdoUpdate::State(
|
||||
|
|
@ -1366,6 +1391,9 @@ fn ido_add_tx(
|
|||
// input#0 is the launcher, nodist, jump to postlaunch
|
||||
// output#0 is the confirmation nft
|
||||
let conf_commitment = first_output.token.as_ref().unwrap().commitment.clone();
|
||||
if conf_commitment.len() < 31 {
|
||||
return Err(anyhow::anyhow!("Incorrect commitment size at output#0"));
|
||||
}
|
||||
updates.push(IdoUpdate::Status("POSTLAUNCH".to_string()));
|
||||
updates.push(IdoUpdate::LaunchTxId(tx.txid().to_blob()));
|
||||
updates.push(IdoUpdate::State(
|
||||
|
|
@ -1397,7 +1425,7 @@ fn ido_add_tx(
|
|||
_ => return Err(anyhow::anyhow!("expecting active parameters")),
|
||||
}
|
||||
// output#0 should contain a token with offering_token_id
|
||||
let first_output = tx.output.get(0).expect("Should have first output!");
|
||||
let first_output = tx.output.get(0).ok_or_else(|| anyhow::anyhow!("Should have first output!"))?;
|
||||
if first_output.token.is_none() ||
|
||||
first_output.token.as_ref().unwrap().id.to_blob() != context.offering_token_id.clone().unwrap_or_default() ||
|
||||
!first_output.token.as_ref().unwrap().has_nft() {
|
||||
|
|
@ -1410,10 +1438,16 @@ fn ido_add_tx(
|
|||
}
|
||||
_ => return Err(anyhow::anyhow!("expecting distributing state")),
|
||||
}
|
||||
let platform_fee_output = tx.output.get(4).expect("platform fee output does not exist!");
|
||||
let platform_fee_output = tx.output.get(4).ok_or_else(|| anyhow::anyhow!("platform fee output does not exist!"))?;
|
||||
if first_output.token.as_ref().unwrap().commitment.len() == 0 {
|
||||
return Err(anyhow::anyhow!("Incorrect commitment size at output#0, should be greater than zero"));
|
||||
}
|
||||
if (first_output.token.as_ref().unwrap().commitment[0] & ITEM_TYPE_BITS) == ITEM_TYPE_DISTRIBUTOR {
|
||||
// output#0 distributor
|
||||
let dist_commitment = first_output.token.as_ref().unwrap().commitment.clone();
|
||||
if dist_commitment.len() < 35 {
|
||||
return Err(anyhow::anyhow!("Incorrect dist_commitment size at output#0"));
|
||||
}
|
||||
updates.push(IdoUpdate::State(
|
||||
IdoState::Distributing(IdoDistributingState {
|
||||
isRefund: (dist_commitment[0] & DISTRIBUTOR_FLAG_IS_REFUND) != 0,
|
||||
|
|
@ -1428,6 +1462,9 @@ fn ido_add_tx(
|
|||
} else if (first_output.token.as_ref().unwrap().commitment[0] & ITEM_TYPE_BITS) == ITEM_TYPE_CONFIRMATION_NFT {
|
||||
// output#0 is the confirmation nft
|
||||
let conf_commitment = first_output.token.as_ref().unwrap().commitment.clone();
|
||||
if conf_commitment.len() < 31 {
|
||||
return Err(anyhow::anyhow!("Incorrect conf_commitment size at output#0"));
|
||||
}
|
||||
updates.push(IdoUpdate::Status("POSTLAUNCH".to_string()));
|
||||
updates.push(IdoUpdate::State(
|
||||
IdoState::PostLaunch(IdoPostLaunchState {
|
||||
|
|
@ -1448,8 +1485,8 @@ fn ido_add_tx(
|
|||
});
|
||||
},
|
||||
"POSTLAUNCH" => {
|
||||
let pp_output = tx.output.get(0).expect("Should have first output!");
|
||||
let collector_p2nfth = tx.output.get(2).expect("Should have third output!");
|
||||
let pp_output = tx.output.get(0).ok_or_else(|| anyhow::anyhow!("Should have first output!"))?;
|
||||
let collector_p2nfth = tx.output.get(2).ok_or_else(|| anyhow::anyhow!("Should have third output!"))?;
|
||||
updates.push(IdoUpdate::Status("DISTRIBUTED".to_string()));
|
||||
let prev_state: &IdoPostLaunchState;
|
||||
match &context.state {
|
||||
|
|
@ -1462,12 +1499,12 @@ fn ido_add_tx(
|
|||
IdoState::Distributed(IdoDistributedState {
|
||||
permanentPool: if pp_output.token.is_none() { None } else { Some(IdoPermanentPoolV0 {
|
||||
tokenAmount: BigInt::from(pp_output.token.as_ref()
|
||||
.expect("pp should have tokens")
|
||||
.ok_or_else(|| anyhow::anyhow!("pp should have tokens"))?
|
||||
.amount),
|
||||
satoshiAmount: BigInt::from(pp_output.value),
|
||||
}) },
|
||||
refundAmount: BigInt::from(collector_p2nfth.token.as_ref()
|
||||
.expect("collector_p2nfth should have tokens")
|
||||
.ok_or_else(|| anyhow::anyhow!("collector_p2nfth should have tokens"))?
|
||||
.amount),
|
||||
discountAmount: prev_state.discountAmount.clone(),
|
||||
collectorEarnedAmount: BigInt::from(collector_p2nfth.value),
|
||||
|
|
@ -1671,7 +1708,7 @@ async fn on_add_ido_tx(
|
|||
.await?;
|
||||
let mut items_tx_map: HashMap<Vec<u8>, Transaction> = HashMap::new();
|
||||
for item in &items {
|
||||
let tx_deser: Transaction = bitcoincash::consensus::deserialize(&item.tx).expect("failed to deserialize tx");
|
||||
let tx_deser: Transaction = bitcoincash::consensus::deserialize(&item.tx).map_err(|e| anyhow::anyhow!("failed to deserialize tx: {e}"))?;
|
||||
items_tx_map.insert(item.txid.clone(), tx_deser);
|
||||
}
|
||||
let mut new_chain: Vec<&IdoTxChainDBRecord> = Vec::new();
|
||||
|
|
@ -1680,20 +1717,20 @@ async fn on_add_ido_tx(
|
|||
new_chain.insert(0, current_item);
|
||||
while current_item.prev_id.is_some() {
|
||||
let prev_id = current_item.prev_id.unwrap();
|
||||
let found_index = items_copy.iter().position(|a| a.id == prev_id).expect("txchain prev item not found!");
|
||||
let found_index = items_copy.iter().position(|a| a.id == prev_id).ok_or_else(|| anyhow::anyhow!("txchain prev item not found!"))?;
|
||||
current_item = items_copy.remove(found_index);
|
||||
new_chain.insert(0, current_item);
|
||||
}
|
||||
if new_chain.get(0).unwrap().txid != ido.preinit_txid {
|
||||
if new_chain.get(0).ok_or_else(|| anyhow::anyhow!("txchain is empty"))?.txid != ido.preinit_txid {
|
||||
return Err(anyhow::anyhow!("txchain entrypoint does not match preinit_txid"));
|
||||
}
|
||||
// start from PREINIT
|
||||
let preinit_tx = items_tx_map.get(&ido.preinit_txid).expect("ido's entrypoint does not exist in the txchain");
|
||||
let preinit_tx = items_tx_map.get(&ido.preinit_txid).ok_or_else(|| anyhow::anyhow!("ido's entrypoint does not exist in the txchain"))?;
|
||||
let mut context = create_ido_context_from_preinit(network, preinit_tx).await?;
|
||||
let mut updates: Vec<IdoUpdate> = Vec::new();
|
||||
for i in 1..new_chain.len() {
|
||||
let item = new_chain.get(i).expect("should not be none!");
|
||||
let item_tx = items_tx_map.get(&item.txid).expect("should not be none!");
|
||||
let item = new_chain.get(i).ok_or_else(|| anyhow::anyhow!("txchain item not found at index"))?;
|
||||
let item_tx = items_tx_map.get(&item.txid).ok_or_else(|| anyhow::anyhow!("txchain tx not found in map"))?;
|
||||
// add tx
|
||||
let result = ido_add_tx(&context, item_tx)?;
|
||||
apply_updates_to_context(&mut context, &result.updates);
|
||||
|
|
@ -1719,13 +1756,17 @@ async fn on_add_ido_tx(
|
|||
.await?;
|
||||
} else {
|
||||
// create context from ido
|
||||
let parameters: IdoParameters = serde_json::from_slice(&ido.parameters)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to parse parameters: {e}"))?;
|
||||
let state: IdoState = serde_json::from_slice(&ido.state)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to parse state: {e}"))?;
|
||||
let mut context: IdoContext = IdoContext {
|
||||
preinit_txid: ido.preinit_txid.clone(),
|
||||
init_txid: ido.init_txid.clone(),
|
||||
launch_txid: ido.launch_txid.clone(),
|
||||
status: ido.status.clone(),
|
||||
parameters: serde_json::from_slice(&ido.parameters).expect("Failed to parse parameters"),
|
||||
state: serde_json::from_slice(&ido.state).expect("Failed to parse state"),
|
||||
parameters,
|
||||
state,
|
||||
is_valid_ido: ido.is_valid,
|
||||
is_token_created_at_preinit: ido.is_token_created_at_preinit,
|
||||
offered_token_id: ido.offered_token_id.clone(),
|
||||
|
|
@ -1786,14 +1827,19 @@ pub async fn index_block(
|
|||
)
|
||||
.await?
|
||||
{
|
||||
let ido = ido_lookup(pool, txchain_item.ido_id)
|
||||
.await?
|
||||
.expect("ido record not found!!");
|
||||
match ido_lookup(pool, txchain_item.ido_id)
|
||||
.await {
|
||||
Ok(Some(ido)) => {
|
||||
match on_add_ido_tx(network, pool, &ido, &txchain_item, tx, block_height)
|
||||
.await {
|
||||
Err(err) => info!("add tx to an ido failed, txid: {}, {}", hex::encode(tx.txid().to_blob()), err),
|
||||
_ => (),
|
||||
}
|
||||
},
|
||||
Err(err) => warn!("ido record not found!!, {}", err),
|
||||
_ => warn!("ido record not found!!"),
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2096,13 +2142,14 @@ mod tests {
|
|||
preinit_txid: Vec<u8>,
|
||||
status: &str,
|
||||
is_valid: bool,
|
||||
is_token_created_at_preinit: bool,
|
||||
offered_token_id: Option<Vec<u8>>,
|
||||
offering_token_id: Option<Vec<u8>>,
|
||||
) -> i64 {
|
||||
sqlx::query(
|
||||
"INSERT INTO ido (preinit_txid, init_txid, launch_txid, offering_token_id,
|
||||
offered_token_id, status, parameters, state, is_valid, txchain_entrypoint, txchain_head)
|
||||
VALUES (?, NULL, NULL, ?, ?, ?, ?, ?, ?, NULL, NULL)",
|
||||
offered_token_id, status, parameters, state, is_valid, is_token_created_at_preinit, txchain_entrypoint, txchain_head)
|
||||
VALUES (?, NULL, NULL, ?, ?, ?, ?, ?, ?, ?, NULL, NULL)",
|
||||
)
|
||||
.bind(preinit_txid)
|
||||
.bind(offering_token_id)
|
||||
|
|
@ -2111,6 +2158,7 @@ mod tests {
|
|||
.bind(b"{}".as_slice())
|
||||
.bind(b"{}".as_slice())
|
||||
.bind(is_valid as i64)
|
||||
.bind(is_token_created_at_preinit as i64)
|
||||
.execute(pool)
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
@ -2270,8 +2318,8 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_idos_returns_all() {
|
||||
let pool = make_pool().await;
|
||||
insert_test_ido(&pool, txid(1), "PREINIT", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(2), "ACTIVE", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(1), "PREINIT", true, true, None, None).await;
|
||||
insert_test_ido(&pool, txid(2), "ACTIVE", true, true, None, None).await;
|
||||
let results = list_idos(&pool, None, None, None, 0, 100).await.unwrap();
|
||||
assert_eq!(results.len(), 2);
|
||||
}
|
||||
|
|
@ -2279,8 +2327,8 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_idos_filter_is_valid() {
|
||||
let pool = make_pool().await;
|
||||
insert_test_ido(&pool, txid(1), "PREINIT", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(2), "PREINIT", false, None, None).await;
|
||||
insert_test_ido(&pool, txid(1), "PREINIT", true, true, None, None).await;
|
||||
insert_test_ido(&pool, txid(2), "PREINIT", false, false, None, None).await;
|
||||
let valid = list_idos(&pool, Some(true), None, None, 0, 100).await.unwrap();
|
||||
assert_eq!(valid.len(), 1);
|
||||
assert!(valid[0].is_valid);
|
||||
|
|
@ -2292,9 +2340,9 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_idos_filter_status() {
|
||||
let pool = make_pool().await;
|
||||
insert_test_ido(&pool, txid(1), "PREINIT", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(2), "ACTIVE", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(3), "ACTIVE", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(1), "PREINIT", true, true, None, None).await;
|
||||
insert_test_ido(&pool, txid(2), "ACTIVE", true, true, None, None).await;
|
||||
insert_test_ido(&pool, txid(3), "ACTIVE", true, true, None, None).await;
|
||||
let active = list_idos(&pool, None, Some("ACTIVE".to_string()), None, 0, 100).await.unwrap();
|
||||
assert_eq!(active.len(), 2);
|
||||
assert!(active.iter().all(|r| r.status == "ACTIVE"));
|
||||
|
|
@ -2304,8 +2352,8 @@ mod tests {
|
|||
async fn list_idos_filter_offered_token_id() {
|
||||
let pool = make_pool().await;
|
||||
let token = vec![0xAB; 32];
|
||||
insert_test_ido(&pool, txid(1), "ACTIVE", true, Some(token.clone()), None).await;
|
||||
insert_test_ido(&pool, txid(2), "ACTIVE", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(1), "ACTIVE", true, true, Some(token.clone()), None).await;
|
||||
insert_test_ido(&pool, txid(2), "ACTIVE", true, true, None, None).await;
|
||||
let filtered = list_idos(&pool, None, None, Some(token), 0, 100).await.unwrap();
|
||||
assert_eq!(filtered.len(), 1);
|
||||
}
|
||||
|
|
@ -2314,7 +2362,7 @@ mod tests {
|
|||
async fn list_idos_pagination() {
|
||||
let pool = make_pool().await;
|
||||
for i in 1..=5u8 {
|
||||
insert_test_ido(&pool, txid(i), "PREINIT", true, None, None).await;
|
||||
insert_test_ido(&pool, txid(i), "PREINIT", true, true, None, None).await;
|
||||
}
|
||||
let page1 = list_idos(&pool, None, None, None, 0, 2).await.unwrap();
|
||||
let page2 = list_idos(&pool, None, None, None, 2, 2).await.unwrap();
|
||||
|
|
@ -2333,7 +2381,7 @@ mod tests {
|
|||
async fn get_ido_by_offering_token_found() {
|
||||
let pool = make_pool().await;
|
||||
let tok = vec![0xCC; 32];
|
||||
insert_test_ido(&pool, txid(1), "ACTIVE", true, None, Some(tok.clone())).await;
|
||||
insert_test_ido(&pool, txid(1), "ACTIVE", true, true, None, Some(tok.clone())).await;
|
||||
let result = get_ido_by_offering_token_id(&pool, tok).await.unwrap();
|
||||
assert!(result.is_some());
|
||||
assert_eq!(result.unwrap().status, "ACTIVE");
|
||||
|
|
@ -2366,7 +2414,7 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_ido_entries_all() {
|
||||
let pool = make_pool().await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, None, None).await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, true, None, None).await;
|
||||
insert_test_entry(&pool, ido_id, txid(10), false).await;
|
||||
insert_test_entry(&pool, ido_id, txid(11), true).await;
|
||||
let all = list_ido_entries(&pool, ido_id, None, 0, 100).await.unwrap();
|
||||
|
|
@ -2376,7 +2424,7 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_ido_entries_filter_distributed() {
|
||||
let pool = make_pool().await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, None, None).await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, true, None, None).await;
|
||||
insert_test_entry(&pool, ido_id, txid(10), false).await;
|
||||
insert_test_entry(&pool, ido_id, txid(11), true).await;
|
||||
insert_test_entry(&pool, ido_id, txid(12), true).await;
|
||||
|
|
@ -2391,8 +2439,8 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_ido_entries_scoped_to_ido() {
|
||||
let pool = make_pool().await;
|
||||
let ido1 = insert_test_ido(&pool, txid(1), "ACTIVE", true, None, None).await;
|
||||
let ido2 = insert_test_ido(&pool, txid(2), "ACTIVE", true, None, None).await;
|
||||
let ido1 = insert_test_ido(&pool, txid(1), "ACTIVE", true, true, None, None).await;
|
||||
let ido2 = insert_test_ido(&pool, txid(2), "ACTIVE", true, true, None, None).await;
|
||||
insert_test_entry(&pool, ido1, txid(10), false).await;
|
||||
insert_test_entry(&pool, ido1, txid(11), false).await;
|
||||
insert_test_entry(&pool, ido2, txid(12), false).await;
|
||||
|
|
@ -2435,7 +2483,7 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_ido_txchain_ordered_oldest_first() {
|
||||
let pool = make_pool().await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, None, None).await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, true, None, None).await;
|
||||
let id_a = insert_txchain_item(&pool, ido_id, txid(10), None).await;
|
||||
let id_b = insert_txchain_item(&pool, ido_id, txid(11), Some(id_a)).await;
|
||||
let id_c = insert_txchain_item(&pool, ido_id, txid(12), Some(id_b)).await;
|
||||
|
|
@ -2451,7 +2499,7 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_ido_txchain_pagination() {
|
||||
let pool = make_pool().await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, None, None).await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, true, None, None).await;
|
||||
let id_a = insert_txchain_item(&pool, ido_id, txid(10), None).await;
|
||||
let id_b = insert_txchain_item(&pool, ido_id, txid(11), Some(id_a)).await;
|
||||
let id_c = insert_txchain_item(&pool, ido_id, txid(12), Some(id_b)).await;
|
||||
|
|
@ -2471,7 +2519,7 @@ mod tests {
|
|||
#[rocket::async_test]
|
||||
async fn list_ido_txchain_no_head_returns_empty() {
|
||||
let pool = make_pool().await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, None, None).await;
|
||||
let ido_id = insert_test_ido(&pool, txid(1), "ACTIVE", true, true, None, None).await;
|
||||
// txchain_head is NULL (default from insert_test_ido)
|
||||
let chain = list_ido_txchain(&pool, ido_id, 0, 100).await.unwrap();
|
||||
assert_eq!(chain.len(), 0);
|
||||
|
|
|
|||
|
|
@ -142,8 +142,6 @@ pub async fn initialize_databases(network: &str, read_slots: ReadSlots) -> Resul
|
|||
create_db_pool(&db_path(db_dir, "ido.db"), read_slots.ido).await;
|
||||
if !db_exists {
|
||||
ido_prepare_tables(&ido_db_write).await;
|
||||
} else {
|
||||
check_db_version(&ido_db_read).await?;
|
||||
}
|
||||
|
||||
Ok(DB {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue