Added total token contributions to saleState account.
This commit is contained in:
parent
14faa868c8
commit
9d26669a4c
|
@ -28,6 +28,7 @@ import {
|
|||
abort_icco_sale_ix,
|
||||
contribute_icco_sale_ix,
|
||||
Pubkey,
|
||||
// test_account_address,
|
||||
} from "../../solana/icco_contributor-node";
|
||||
|
||||
// Solana
|
||||
|
@ -444,6 +445,158 @@ describe("Solana dev Tests", () => {
|
|||
}
|
||||
})();
|
||||
});
|
||||
|
||||
xtest("call into init_icco_sale minitest", (done) => {
|
||||
(async () => {
|
||||
try {
|
||||
console.log("-->> minitest");
|
||||
|
||||
// create initSale using conductor on ETH.
|
||||
const ethProvider = new ethers.providers.WebSocketProvider(
|
||||
ETH_NODE_URL
|
||||
);
|
||||
const contributorConfigs: EthContributorConfig[] = [
|
||||
{
|
||||
chainId: CHAIN_ID_ETH,
|
||||
wallet: new ethers.Wallet(ETH_PRIVATE_KEY1, ethProvider),
|
||||
collateralAddress: WETH_ADDRESS,
|
||||
conversionRate: "1",
|
||||
},
|
||||
// TBD Need to add solana?
|
||||
];
|
||||
const conductorConfig = contributorConfigs[0];
|
||||
// make sale token. mint 10 and sell 10%
|
||||
const tokenAddress = await deployTokenOnEth(
|
||||
ETH_NODE_URL,
|
||||
"Icco-Test",
|
||||
"ICCO",
|
||||
ethers.utils.parseUnits("10").toString(),
|
||||
conductorConfig.wallet
|
||||
);
|
||||
console.log("Token Address: ", tokenAddress);
|
||||
const buyers: EthBuyerConfig[] = [
|
||||
// native weth
|
||||
{
|
||||
chainId: CHAIN_ID_ETH,
|
||||
wallet: new ethers.Wallet(ETH_PRIVATE_KEY2, ethProvider),
|
||||
collateralAddress: WETH_ADDRESS,
|
||||
contribution: "6",
|
||||
tokenIndex: 0,
|
||||
},
|
||||
];
|
||||
|
||||
// we need to set up all of the accepted tokens (natives plus their wrapped versions)
|
||||
const acceptedTokens = await makeAcceptedTokensFromConfigs(
|
||||
contributorConfigs,
|
||||
buyers
|
||||
);
|
||||
|
||||
const tokenAmount = "1";
|
||||
const minRaise = "10"; // eth units
|
||||
const maxRaise = "14";
|
||||
const saleDuration = 60; // seconds
|
||||
// get the time
|
||||
const saleStart =
|
||||
(await makeSaleStartFromLastBlock(contributorConfigs)) + 20; // So it can be aborted "early".
|
||||
|
||||
const decimals = 9;
|
||||
const saleEnd = saleStart + saleDuration;
|
||||
console.info("--> Sale Start: ", saleStart);
|
||||
const saleInitVaa = await createSaleOnEthAndGetVaa(
|
||||
conductorConfig.wallet,
|
||||
conductorConfig.chainId,
|
||||
tokenAddress,
|
||||
ethers.utils.parseUnits(tokenAmount, decimals),
|
||||
ethers.utils.parseUnits(minRaise),
|
||||
ethers.utils.parseUnits(maxRaise),
|
||||
saleStart,
|
||||
saleEnd,
|
||||
acceptedTokens
|
||||
);
|
||||
const saleInit = await parseSaleInit(saleInitVaa);
|
||||
console.info(
|
||||
"Sale Init VAA:",
|
||||
Buffer.from(saleInitVaa).toString("hex")
|
||||
);
|
||||
|
||||
// Wallet (payer) account decode
|
||||
const privateKeyDecoded = Uint8Array.from(
|
||||
SOLANA_WALLET_PK.split(",").map((s) => parseInt(s))
|
||||
);
|
||||
const walletAccount = Keypair.fromSecretKey(privateKeyDecoded);
|
||||
// console.log(walletAccount.publicKey.toString()); // check "6sbzC1eH4FTujJXWj51eQe25cYvr4xfXbJ1vAj7j2k5J"
|
||||
|
||||
// Log Solana VAA PDA address.
|
||||
const init_vaa_pda_pk = new PublicKey(
|
||||
vaa_address(SOLANA_BRIDGE_ADDR, saleInitVaa)
|
||||
);
|
||||
// console.log("bbrp init_sale vaa PDA: ", init_vaa_pda_pk.toString());
|
||||
|
||||
// Make init_icco_sale_ix and call it
|
||||
{
|
||||
// post VAA on solana.
|
||||
await postVaaSolanaWithRetry(
|
||||
solanaConnection,
|
||||
async (transaction) => {
|
||||
transaction.partialSign(walletAccount);
|
||||
return transaction;
|
||||
},
|
||||
SOLANA_BRIDGE_ADDR,
|
||||
walletAccount.publicKey.toString(),
|
||||
Buffer.from(saleInitVaa),
|
||||
0
|
||||
);
|
||||
/*
|
||||
const ta_key = test_account_address(
|
||||
SOLANA_CONTRIBUTOR_ADDR,
|
||||
BigInt(saleInit.saleId.toString())
|
||||
);
|
||||
console.log("test_account_address: ", ta_key.toString());
|
||||
*/
|
||||
// Create custody account(s) to hold contributet tokens.
|
||||
const custody_addr = icco_sale_custody_account_address(
|
||||
SOLANA_CONTRIBUTOR_ADDR,
|
||||
BigInt(saleInit.saleId.toString()),
|
||||
SOLANA_TEST_TOKEN_MINT
|
||||
);
|
||||
console.log("custody_addr: ", custody_addr.toString());
|
||||
|
||||
const ix_create_custudy_acct = ixFromRust(
|
||||
create_icco_sale_custody_account_ix(
|
||||
SOLANA_CONTRIBUTOR_ADDR,
|
||||
SOLANA_BRIDGE_ADDR,
|
||||
walletAccount.publicKey.toString(),
|
||||
saleInitVaa,
|
||||
SOLANA_TEST_TOKEN_MINT, // see wormhole/docs/devnet.md
|
||||
0
|
||||
)
|
||||
);
|
||||
const tx_create_custudy_acct = new Transaction().add(
|
||||
ix_create_custudy_acct
|
||||
);
|
||||
const tx_id_create_custudy_acct =
|
||||
await solanaConnection.sendTransaction(
|
||||
tx_create_custudy_acct,
|
||||
[walletAccount],
|
||||
{
|
||||
skipPreflight: false,
|
||||
preflightCommitment: "singleGossip",
|
||||
}
|
||||
);
|
||||
await solanaConnection.confirmTransaction(tx_id_create_custudy_acct);
|
||||
}
|
||||
// Done here.
|
||||
ethProvider.destroy();
|
||||
console.log("----- init_icco_sale + abort_icco_sale done -----");
|
||||
done();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
done(
|
||||
"An error occurred in init_icco_sale abort_icco_sale contributor test"
|
||||
);
|
||||
}
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
function dumpInstructionAccounts(ixw: any) {
|
||||
|
|
|
@ -1 +1,6 @@
|
|||
[14,173,153,4,176,224,201,111,32,237,183,185,159,247,22,161,89,84,215,209,212,137,10,92,157,49,29,192,101,164,152,70,87,65,8,174,214,157,175,126,98,90,54,24,100,177,247,77,19,112,47,44,165,109,233,102,14,86,109,29,134,145,132,141]
|
||||
[
|
||||
14, 173, 153, 4, 176, 224, 201, 111, 32, 237, 183, 185, 159, 247, 22, 161, 89,
|
||||
84, 215, 209, 212, 137, 10, 92, 157, 49, 29, 192, 101, 164, 152, 70, 87, 65,
|
||||
8, 174, 214, 157, 175, 126, 98, 90, 54, 24, 100, 177, 247, 77, 19, 112, 47,
|
||||
44, 165, 109, 233, 102, 14, 86, 109, 29, 134, 145, 132, 141
|
||||
]
|
||||
|
|
|
@ -17,8 +17,9 @@ pub type CoreBridge<'a, const STATE: AccountState> = Data<'a, BridgeData, { STAT
|
|||
|
||||
pub type EmitterAccount<'b> = Derive<Info<'b>, "emitter">;
|
||||
|
||||
|
||||
///-------------------------------------------------------------------
|
||||
/// Cntributor Config.
|
||||
/// Contributor Config.
|
||||
pub type ConfigAccount<'b, const STATE: AccountState> =
|
||||
Derive<Data<'b, Config, { STATE }>, "config">;
|
||||
|
||||
|
@ -28,14 +29,14 @@ pub type ConfigAccount<'b, const STATE: AccountState> =
|
|||
pub type SaleStateAccount<'b, const STATE: AccountState> =
|
||||
Data<'b, SaleState, { STATE }>;
|
||||
|
||||
pub struct SaleStateDerivationData {
|
||||
pub struct SaleStateAccountDerivationData {
|
||||
pub sale_id: u128,
|
||||
}
|
||||
|
||||
impl<'b, const STATE: AccountState> Seeded<&SaleStateDerivationData>
|
||||
impl<'b, const STATE: AccountState> Seeded<&SaleStateAccountDerivationData>
|
||||
for SaleStateAccount<'b, { STATE }>
|
||||
{
|
||||
fn seeds(accs: &SaleStateDerivationData) -> Vec<Vec<u8>> {
|
||||
fn seeds(accs: &SaleStateAccountDerivationData) -> Vec<Vec<u8>> {
|
||||
vec![
|
||||
String::from("state").as_bytes().to_vec(),
|
||||
accs.sale_id.to_be_bytes().to_vec(),
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
//#![allow(unused_imports)]
|
||||
|
||||
use crate::{
|
||||
messages::SaleAbort,
|
||||
messages::*,
|
||||
accounts::{
|
||||
ConfigAccount,
|
||||
SaleStateAccount,
|
||||
SaleStateDerivationData,
|
||||
// SaleStateAccountDerivationData,
|
||||
},
|
||||
errors::Error::*,
|
||||
};
|
||||
|
@ -32,33 +31,32 @@ use bridge::{
|
|||
};
|
||||
|
||||
|
||||
|
||||
#[derive(FromAccounts)]
|
||||
pub struct AbortIccoSale<'b> {
|
||||
pub payer: Mut<Signer<AccountInfo<'b>>>,
|
||||
pub config: ConfigAccount<'b, { AccountState::Initialized }>,
|
||||
pub sale_state: Mut<SaleStateAccount<'b, { AccountState::Initialized }>>,
|
||||
pub abort_sale_vaa: ClaimableVAA<'b, SaleAbort>,
|
||||
pub rent: Sysvar<'b, Rent>,
|
||||
pub clock: Sysvar<'b, Clock>,
|
||||
// Sale state is in ctx.accounts[7];
|
||||
}
|
||||
|
||||
impl<'a> From<&AbortIccoSale<'a>> for SaleStateDerivationData {
|
||||
/*
|
||||
// May need this later Just for PDA verification.
|
||||
impl<'a> From<&AbortIccoSale<'a>> for SaleStateAccountDerivationData {
|
||||
fn from(accs: &AbortIccoSale<'a>) -> Self {
|
||||
SaleStateDerivationData {
|
||||
SaleStateAccountDerivationData {
|
||||
sale_id: accs.abort_sale_vaa.sale_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// No data so far.
|
||||
#[derive(BorshDeserialize, BorshSerialize, Default)]
|
||||
pub struct AbortIccoSaleData {
|
||||
}
|
||||
|
||||
// impl<'b> InstructionContext<'b> for AbortIccoSale<'b> {
|
||||
// }
|
||||
|
||||
pub fn abort_icco_sale(
|
||||
ctx: &ExecutionContext,
|
||||
accs: &mut AbortIccoSale,
|
||||
|
@ -81,25 +79,22 @@ pub fn abort_icco_sale(
|
|||
// let end_time = accs.init_sale_vaa.get_sale_end(&accs.init_sale_vaa.meta().payload[..]).1 as i64;
|
||||
// msg!("time: {:?} start: {:?} end: {:?}", now_time, start_time, end_time);
|
||||
|
||||
|
||||
// let sale_id = accs.init_sale_vaa.sale_id;
|
||||
|
||||
// Verify that the sale_state account PDA was derived correctly
|
||||
let derivation_data: SaleStateDerivationData = (&*accs).into();
|
||||
accs.sale_state.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||
// let sale_id = accs.init_sale_vaa.sale_id;
|
||||
// let derivation_data: SaleStateAccountDerivationData = (&*accs).into();
|
||||
// accs.sale_state.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||
let sale_state_account_info = &ctx.accounts[7];
|
||||
//msg!("state_key: {:?}", sale_state_account_info.key);
|
||||
|
||||
msg!("state_key: {:?}", accs.sale_state.info().key);
|
||||
|
||||
// sale_state account set
|
||||
if accs.sale_state.is_sealed {
|
||||
let mut state_data = sale_state_account_info.data.borrow_mut();
|
||||
if get_sale_state_sealed(&state_data) {
|
||||
return Err(SaleHasBeenSealed.into());
|
||||
}
|
||||
if accs.sale_state.is_aborted {
|
||||
if get_sale_state_aborted(&state_data) {
|
||||
return Err(SaleHasBeenAborted.into());
|
||||
}
|
||||
|
||||
// Set sale as aborted and claim VAA on this chain
|
||||
accs.sale_state.is_aborted = true;
|
||||
set_sale_state_aborted(& mut state_data, true);
|
||||
accs.abort_sale_vaa.claim(ctx, accs.payer.key)?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
use std::mem::size_of_val;
|
||||
use crate::{
|
||||
messages::SaleInit,
|
||||
messages::*,
|
||||
accounts::{
|
||||
ConfigAccount,
|
||||
SaleStateAccount,
|
||||
SaleStateDerivationData,
|
||||
// SaleStateAccountDerivationData,
|
||||
CustodySigner,
|
||||
CustodyAccount,
|
||||
CustodyAccountDerivationData,
|
||||
|
@ -58,7 +58,6 @@ use bridge::{
|
|||
pub struct ContributeIccoSale<'b> {
|
||||
pub payer: Mut<Signer<AccountInfo<'b>>>,
|
||||
pub config: ConfigAccount<'b, { AccountState::Initialized }>,
|
||||
pub sale_state: SaleStateAccount<'b, { AccountState::Initialized }>, // R/O here
|
||||
pub init_sale_vaa: ClaimedVAA<'b, SaleInit>, // Was claimed.
|
||||
|
||||
pub contribution_state: Mut<ContributionStateAccount<'b, { AccountState::MaybeInitialized }>>,
|
||||
|
@ -70,15 +69,18 @@ pub struct ContributeIccoSale<'b> {
|
|||
pub custody: Mut<CustodyAccount<'b, { AccountState::Initialized }>>,
|
||||
|
||||
pub clock: Sysvar<'b, Clock>,
|
||||
// Sale state is in ctx.accounts[11];
|
||||
}
|
||||
|
||||
impl<'a> From<&ContributeIccoSale<'a>> for SaleStateDerivationData {
|
||||
/*
|
||||
impl<'a> From<&ContributeIccoSale<'a>> for SaleStateAccountDerivationData {
|
||||
fn from(accs: &ContributeIccoSale<'a>) -> Self {
|
||||
SaleStateDerivationData {
|
||||
SaleStateAccountDerivationData {
|
||||
sale_id: accs.init_sale_vaa.sale_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl<'a> From<&ContributeIccoSale<'a>> for CustodyAccountDerivationData {
|
||||
fn from(accs: &ContributeIccoSale<'a>) -> Self {
|
||||
|
@ -116,14 +118,18 @@ pub fn contribute_icco_sale(
|
|||
) -> Result<()> {
|
||||
msg!("In contribute_icco_sale!");
|
||||
|
||||
let sale_state_account_info = &ctx.accounts[11];
|
||||
//msg!("state_key: {:?}", sale_state_account_info.key);
|
||||
let mut state_data = sale_state_account_info.data.borrow_mut();
|
||||
|
||||
// Check sale status.
|
||||
if accs.sale_state.is_sealed || accs.sale_state.is_aborted {
|
||||
if get_sale_state_sealed(&state_data) || get_sale_state_aborted(&state_data) {
|
||||
return Err(SaleSealedOrAborted.into());
|
||||
}
|
||||
|
||||
/*
|
||||
// TBD This does not work yet. EVM Time is not Linux.
|
||||
// Check if sale started.
|
||||
/*
|
||||
|
||||
let now_time = accs.clock.unix_timestamp as u128; // i64 ->u128
|
||||
if now_time < accs.init_sale_vaa.get_sale_start(&accs.init_sale_vaa.meta().payload[..]).0 {
|
||||
return Err(SaleHasNotStarted.into());
|
||||
|
@ -132,6 +138,7 @@ pub fn contribute_icco_sale(
|
|||
return Err(SaleHasEnded.into());
|
||||
}
|
||||
*/
|
||||
|
||||
// Make sure token Idx matches passed in token mint addr.
|
||||
/*
|
||||
let token_idx = data.token_idx;
|
||||
|
@ -165,7 +172,11 @@ pub fn contribute_icco_sale(
|
|||
// invoke_seeded(&transfer_ix, ctx, &accs.payer, None)?;
|
||||
// invoke_seeded(&transfer_ix, ctx, &accs.authority_signer, None)?;
|
||||
|
||||
// store new amount.
|
||||
// store new amount in Custody and State accounts.
|
||||
let token_idx = data.token_idx;
|
||||
let tmp_v = get_sale_state_contribution(&state_data, token_idx) + data.amount;
|
||||
set_sale_state_contribution(& mut state_data, token_idx, tmp_v);
|
||||
// accs.sale_state.contributions[token_idx] = accs.sale_state.contributions[token_idx] + data.amount;
|
||||
accs.contribution_state.amount = accs.contribution_state.amount + data.amount;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -2,27 +2,13 @@
|
|||
//#![allow(unused_must_use)]
|
||||
//#![allow(unused_imports)]
|
||||
|
||||
//use core::convert::TryInto;
|
||||
//use std::mem::size_of_val;
|
||||
|
||||
// use std::{
|
||||
// error::Error,
|
||||
// io::{
|
||||
// Cursor,
|
||||
// Read,
|
||||
// Write,
|
||||
// },
|
||||
// // str::Utf8Error,
|
||||
// // string::FromUtf8Error,
|
||||
// };
|
||||
|
||||
use crate::{
|
||||
messages::SaleInit,
|
||||
accounts::{
|
||||
simple_account::create_simple_account,
|
||||
accounts::{
|
||||
ConfigAccount,
|
||||
SaleStateAccount,
|
||||
SaleStateDerivationData,
|
||||
// CustodySigner,
|
||||
SaleStateAccountDerivationData,
|
||||
CustodyAccount,
|
||||
CustodyAccountDerivationData,
|
||||
},
|
||||
|
@ -33,7 +19,10 @@ use crate::{
|
|||
use solana_program::msg;
|
||||
|
||||
use solana_program::{
|
||||
// pubkey::Pubkey,
|
||||
// system_instruction,
|
||||
account_info::AccountInfo,
|
||||
// program::invoke,
|
||||
program::invoke_signed,
|
||||
// program_error::ProgramError,
|
||||
// pubkey::Pubkey,
|
||||
|
@ -46,17 +35,10 @@ use solitaire::{
|
|||
*,
|
||||
};
|
||||
|
||||
// use wormhole_sdk::{VAA};
|
||||
|
||||
use bridge::{
|
||||
vaa::{
|
||||
ClaimableVAA,
|
||||
},
|
||||
// error::Error::{
|
||||
// VAAAlreadyExecuted,
|
||||
// VAAInvalid,
|
||||
// },
|
||||
|
||||
// CHAIN_ID_SOLANA,
|
||||
};
|
||||
|
||||
|
@ -77,6 +59,7 @@ pub struct CreateIccoSaleCustodyAccount<'b> {
|
|||
|
||||
pub rent: Sysvar<'b, Rent>,
|
||||
pub clock: Sysvar<'b, Clock>,
|
||||
// Account [11] is the test.
|
||||
}
|
||||
|
||||
impl<'a> From<&CreateIccoSaleCustodyAccount<'a>> for CustodyAccountDerivationData {
|
||||
|
@ -93,6 +76,7 @@ impl<'a> From<&CreateIccoSaleCustodyAccount<'a>> for CustodyAccountDerivationDat
|
|||
pub struct CreateIccoSaleCustodyAccountData {
|
||||
}
|
||||
|
||||
|
||||
pub fn create_icco_sale_custody_account(
|
||||
ctx: &ExecutionContext,
|
||||
accs: &mut CreateIccoSaleCustodyAccount,
|
||||
|
@ -115,7 +99,7 @@ pub fn create_icco_sale_custody_account(
|
|||
let sale_id = accs.init_sale_vaa.sale_id;
|
||||
msg!("sale_id: {:?}", sale_id);
|
||||
|
||||
// Create and init custody account if needed. It may be iunitialized if previous init sale failed after accounts were created.
|
||||
// Create and init custody account as needed. It may be initialized already, if previous init sale failed after accounts were created.
|
||||
// https://github.com/certusone/wormhole/blob/1792141307c3979b1f267af3e20cfc2f011d7051/solana/modules/token_bridge/program/src/api/transfer.rs#L159
|
||||
if !accs.custody.is_initialized() {
|
||||
accs.custody.create(&(&*accs).into(), ctx, accs.payer.key, Exempt)?;
|
||||
|
@ -132,30 +116,28 @@ pub fn create_icco_sale_custody_account(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// ctx.program_id, // accs.payer.info().key, // accs.custody_signer.key,
|
||||
|
||||
|
||||
|
||||
|
||||
#[derive(FromAccounts)]
|
||||
pub struct InitIccoSale<'b> {
|
||||
pub payer: Mut<Signer<AccountInfo<'b>>>,
|
||||
pub config: ConfigAccount<'b, { AccountState::Initialized }>, // Must be created before Init
|
||||
pub sale_state: Mut<SaleStateAccount<'b, { AccountState::Uninitialized }>>, // Must not be created yet
|
||||
|
||||
pub init_sale_vaa: ClaimableVAA<'b, SaleInit>, // Claimed here.
|
||||
|
||||
pub rent: Sysvar<'b, Rent>,
|
||||
pub clock: Sysvar<'b, Clock>,
|
||||
// Sale state is in ctx.accounts[7];
|
||||
}
|
||||
|
||||
impl<'a> From<&InitIccoSale<'a>> for SaleStateDerivationData {
|
||||
/*
|
||||
// May need this later Just for PDA verification.
|
||||
impl<'a> From<&InitIccoSale<'a>> for SaleStateAccountDerivationData {
|
||||
fn from(accs: &InitIccoSale<'a>) -> Self {
|
||||
SaleStateDerivationData {
|
||||
SaleStateAccountDerivationData {
|
||||
sale_id: accs.init_sale_vaa.sale_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// No data so far. All is in VAA Account
|
||||
#[derive(BorshDeserialize, BorshSerialize, Default)]
|
||||
|
@ -184,30 +166,39 @@ pub fn init_icco_sale(
|
|||
return Err(VAAInvalidEmitterChain.into());
|
||||
}
|
||||
|
||||
|
||||
let now_time = accs.clock.unix_timestamp;
|
||||
let start_time = accs.init_sale_vaa.get_sale_start(&accs.init_sale_vaa.meta().payload[..]).1 as i64;
|
||||
let end_time = accs.init_sale_vaa.get_sale_end(&accs.init_sale_vaa.meta().payload[..]).1 as i64;
|
||||
msg!("time: {:?} start: {:?} end: {:?}", now_time, start_time, end_time);
|
||||
|
||||
|
||||
let sale_id = accs.init_sale_vaa.sale_id;
|
||||
msg!("sale_id: {:?}", sale_id);
|
||||
|
||||
/* BEFORE
|
||||
// Verify that the sale_state account PDA was derived correctly
|
||||
let derivation_data: SaleStateDerivationData = (&*accs).into();
|
||||
accs.sale_state.verify_derivation(ctx.program_id, &derivation_data)?;
|
||||
// msg!("state_key: {:?}", accs.sale_state.info().key);
|
||||
|
||||
// Create sale_state account. (it was Uninitialized coming in)
|
||||
// if !accs.sale_state.is_initialized() {
|
||||
accs.sale_state.create(&(&*accs).into(), ctx, accs.payer.key, Exempt)?;
|
||||
//}
|
||||
|
||||
// [Check if all Solana tokens exist??] Custodian accounts are created before this call.
|
||||
|
||||
*/
|
||||
// Create account using Solana API.
|
||||
msg!("ctx accounts Cnt: {}", ctx.accounts.len());
|
||||
let sale_state_account_info = &ctx.accounts[7];
|
||||
|
||||
if **sale_state_account_info.lamports.borrow() > 0 {
|
||||
return Err(SaleStateIsAlredyInitialized.into());
|
||||
} else {
|
||||
create_simple_account (ctx,
|
||||
sale_state_account_info.key,
|
||||
accs.payer.key,
|
||||
2 + 8 * accs.init_sale_vaa.token_cnt as usize,
|
||||
&SaleStateAccount::<'_, { AccountState::Uninitialized }>::seeds(&SaleStateAccountDerivationData{sale_id: sale_id}
|
||||
))?;
|
||||
}
|
||||
|
||||
// If all good - Prevent vaa double processing
|
||||
accs.init_sale_vaa.claim(ctx, accs.payer.key)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ pub enum Error {
|
|||
SaleHasEnded,
|
||||
SaleHasBeenSealed,
|
||||
SaleHasBeenAborted,
|
||||
VAATokenCountExceeded,
|
||||
SaleStateIsAlredyInitialized,
|
||||
TestAccountError,
|
||||
}
|
||||
|
||||
/// Errors thrown by the program will bubble up to the solitaire wrapper, which needs a way to
|
||||
|
|
|
@ -7,18 +7,17 @@ use crate::{
|
|||
AuthoritySigner,
|
||||
ConfigAccount,
|
||||
SaleStateAccount,
|
||||
SaleStateDerivationData,
|
||||
SaleStateAccountDerivationData,
|
||||
CustodyAccount,
|
||||
CustodyAccountDerivationData,
|
||||
CustodySigner,
|
||||
EmitterAccount,
|
||||
// Endpoint,
|
||||
// EndpointDerivationData,
|
||||
// MintSigner,
|
||||
SplTokenMeta,
|
||||
SplTokenMetaDerivationData,
|
||||
ContributionStateAccount,
|
||||
ContributionStateAccountDerivationData,
|
||||
// TestAccount,
|
||||
// TestAccountDerivationData,
|
||||
},
|
||||
api::{
|
||||
CreateIccoSaleCustodyAccountData,
|
||||
|
@ -130,6 +129,7 @@ pub fn create_icco_sale_custody_account(
|
|||
_token_index: u8, // TBD For validation against VAA.
|
||||
) -> Instruction {
|
||||
let config_key = ConfigAccount::<'_, { AccountState::Initialized }>::key(None, &program_id);
|
||||
// let test_key = TestAccount::<'_, { AccountState::Uninitialized }>::key(&TestAccountDerivationData{sale_id: sale_id}, &program_id);
|
||||
let custody_key = CustodyAccount::<'_, { AccountState::MaybeInitialized }>::key(&CustodyAccountDerivationData{sale_id: sale_id, mint: token_mint}, &program_id);
|
||||
let claim = Claim::<'_, { AccountState::Uninitialized }>::key(
|
||||
&ClaimDerivationData {
|
||||
|
@ -154,6 +154,7 @@ pub fn create_icco_sale_custody_account(
|
|||
AccountMeta::new_readonly(solana_program::sysvar::clock::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
AccountMeta::new_readonly(spl_token::id(), false),
|
||||
// AccountMeta::new(test_key, false),
|
||||
],
|
||||
data: (
|
||||
crate::instruction::Instruction::CreateIccoSaleCustodyAccount,
|
||||
|
@ -176,7 +177,7 @@ pub fn init_icco_sale(
|
|||
sequence: u64,
|
||||
) -> Instruction {
|
||||
let config_key = ConfigAccount::<'_, { AccountState::Initialized }>::key(None, &program_id);
|
||||
let state_key = SaleStateAccount::<'_, { AccountState::Uninitialized }>::key(&SaleStateDerivationData{sale_id: sale_id}, &program_id);
|
||||
let state_key = SaleStateAccount::<'_, { AccountState::Uninitialized }>::key(&SaleStateAccountDerivationData{sale_id: sale_id}, &program_id);
|
||||
|
||||
let claim = Claim::<'_, { AccountState::Uninitialized }>::key(
|
||||
&ClaimDerivationData {
|
||||
|
@ -192,13 +193,12 @@ pub fn init_icco_sale(
|
|||
accounts: vec![
|
||||
AccountMeta::new(payer, true),
|
||||
AccountMeta::new_readonly(config_key, false),
|
||||
AccountMeta::new(state_key, false),
|
||||
AccountMeta::new_readonly(payload_message, false),
|
||||
AccountMeta::new(claim, false),
|
||||
// AccountMeta::new(program_id, false),
|
||||
AccountMeta::new_readonly(solana_program::sysvar::rent::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::sysvar::clock::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
AccountMeta::new(state_key, false),
|
||||
],
|
||||
|
||||
data: (
|
||||
|
@ -210,8 +210,14 @@ pub fn init_icco_sale(
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn get_test_account_address (program_id: Pubkey, sale_id: u128) -> Pubkey {
|
||||
TestAccount::<'_, { AccountState::Initialized }>::key(&TestAccountDerivationData{sale_id: sale_id}, &program_id)
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn get_icco_state_address (program_id: Pubkey, sale_id: u128) -> Pubkey {
|
||||
SaleStateAccount::<'_, { AccountState::Initialized }>::key(&SaleStateDerivationData{sale_id: sale_id}, &program_id)
|
||||
SaleStateAccount::<'_, { AccountState::Initialized }>::key(&SaleStateAccountDerivationData{sale_id: sale_id}, &program_id)
|
||||
}
|
||||
|
||||
pub fn get_icco_sale_custody_account_address(program_id: Pubkey, sale_id: u128, token_mint: Pubkey) -> Pubkey {
|
||||
|
@ -228,7 +234,7 @@ pub fn abort_icco_sale(
|
|||
sequence: u64,
|
||||
) -> Instruction {
|
||||
let config_key = ConfigAccount::<'_, { AccountState::Initialized }>::key(None, &program_id);
|
||||
let state_key = SaleStateAccount::<'_, { AccountState::Initialized }>::key(&SaleStateDerivationData{sale_id: sale_id}, &program_id);
|
||||
let state_key = SaleStateAccount::<'_, { AccountState::Initialized }>::key(&SaleStateAccountDerivationData{sale_id: sale_id}, &program_id);
|
||||
|
||||
let claim = Claim::<'_, { AccountState::Uninitialized }>::key(
|
||||
&ClaimDerivationData {
|
||||
|
@ -244,13 +250,13 @@ pub fn abort_icco_sale(
|
|||
accounts: vec![
|
||||
AccountMeta::new(payer, true),
|
||||
AccountMeta::new_readonly(config_key, false),
|
||||
AccountMeta::new(state_key, false),
|
||||
AccountMeta::new_readonly(payload_message, false),
|
||||
AccountMeta::new(claim, false),
|
||||
// AccountMeta::new(program_id, false),
|
||||
AccountMeta::new_readonly(solana_program::sysvar::rent::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::sysvar::clock::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
AccountMeta::new(state_key, false),
|
||||
],
|
||||
|
||||
data: (
|
||||
|
@ -277,7 +283,7 @@ pub fn contribute_icco_sale(
|
|||
amount: u64,
|
||||
) -> Instruction {
|
||||
let config_key = ConfigAccount::<'_, { AccountState::Initialized }>::key(None, &program_id);
|
||||
let state_key = SaleStateAccount::<'_, { AccountState::Initialized }>::key(&SaleStateDerivationData{sale_id: sale_id}, &program_id);
|
||||
let state_key = SaleStateAccount::<'_, { AccountState::Initialized }>::key(&SaleStateAccountDerivationData{sale_id: sale_id}, &program_id);
|
||||
let contribution_state_key =
|
||||
ContributionStateAccount::<'_, { AccountState::MaybeInitialized }>::key(&ContributionStateAccountDerivationData{
|
||||
sale_id: sale_id,
|
||||
|
@ -291,7 +297,6 @@ pub fn contribute_icco_sale(
|
|||
accounts: vec![
|
||||
AccountMeta::new(payer, true),
|
||||
AccountMeta::new_readonly(config_key, false),
|
||||
AccountMeta::new_readonly(state_key, false),
|
||||
AccountMeta::new_readonly(payload_message, false),
|
||||
AccountMeta::new(contribution_state_key, false),
|
||||
AccountMeta::new(from_account, false),
|
||||
|
@ -302,6 +307,7 @@ pub fn contribute_icco_sale(
|
|||
AccountMeta::new_readonly(solana_program::sysvar::rent::id(), false),
|
||||
AccountMeta::new_readonly(solana_program::system_program::id(), false),
|
||||
AccountMeta::new_readonly(spl_token::id(), false),
|
||||
AccountMeta::new(state_key, false),
|
||||
],
|
||||
data: (
|
||||
crate::instruction::Instruction::ContributeIccoSale,
|
||||
|
|
|
@ -21,6 +21,7 @@ pub mod errors;
|
|||
pub mod messages;
|
||||
pub mod types;
|
||||
pub mod claimed_vaa;
|
||||
pub mod simple_account;
|
||||
|
||||
pub use api::{
|
||||
contribute_icco_sale, init_icco_sale, initialize, create_icco_sale_custody_account, abort_icco_sale,
|
||||
|
|
|
@ -26,6 +26,10 @@ fn read_u16(buf: &[u8]) -> u16 {
|
|||
u16::from_be_bytes(buf[0..2].try_into().unwrap())
|
||||
}
|
||||
|
||||
fn read_u64(buf: &[u8]) -> u64 {
|
||||
u64::from_be_bytes(buf[0..8].try_into().unwrap())
|
||||
}
|
||||
|
||||
fn read_u128(buf: &[u8]) -> u128 {
|
||||
u128::from_be_bytes(buf[0..16].try_into().unwrap())
|
||||
}
|
||||
|
@ -35,7 +39,31 @@ fn read_u256(buf: &[u8]) -> (u128, u128) {
|
|||
}
|
||||
|
||||
/// -------------------------------------------------------------------
|
||||
/// Zero-copy from VAA payload for Init Sale.
|
||||
/// sale_state getters/setters
|
||||
pub fn get_sale_state_sealed(bf: &[u8]) -> bool {
|
||||
bf[0] != 0
|
||||
}
|
||||
pub fn set_sale_state_sealed(bf: & mut [u8], v: bool) {
|
||||
bf[0] = if v {1} else {0};
|
||||
}
|
||||
|
||||
pub fn get_sale_state_aborted(bf: &[u8]) -> bool {
|
||||
bf[1] != 0
|
||||
}
|
||||
pub fn set_sale_state_aborted(bf: & mut [u8], v: bool) {
|
||||
bf[1] = if v {1} else {0};
|
||||
}
|
||||
|
||||
pub fn get_sale_state_contribution(bf: &[u8], token_idx: u8) -> u64 {
|
||||
read_u64(&bf[(2 + 8 * token_idx) as usize..])
|
||||
}
|
||||
pub fn set_sale_state_contribution(bf: & mut [u8], token_idx: u8, v: u64) {
|
||||
let n = (2 + 8 * token_idx) as usize;
|
||||
bf[n..n+8].clone_from_slice(&v.to_be_bytes()[..]);
|
||||
}
|
||||
|
||||
/// -------------------------------------------------------------------
|
||||
/// From VAA payload for SaleAbort.
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[allow(non_snake_case)]
|
||||
pub struct SaleAbort {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
use solana_program::{
|
||||
pubkey::Pubkey,
|
||||
system_instruction,
|
||||
//account_info::AccountInfo,
|
||||
program::invoke,
|
||||
program::invoke_signed,
|
||||
// program_error::ProgramError,
|
||||
// pubkey::Pubkey,
|
||||
sysvar::rent::Rent,
|
||||
};
|
||||
|
||||
use solitaire::*;
|
||||
|
||||
pub fn create_simple_account (ctx: &ExecutionContext, pubkey: &Pubkey, payer: &Pubkey, size: usize, vseeds: &Vec<Vec<u8>>) -> Result<()> {
|
||||
let target_rent = Rent::default().minimum_balance(size);
|
||||
// top up account to target rent
|
||||
let transfer_ix = system_instruction::transfer(payer, pubkey, target_rent);
|
||||
invoke(&transfer_ix, ctx.accounts)?;
|
||||
// msg!("transferred {} lamports", target_rent);
|
||||
|
||||
// invoke is just a synonym for invoke_signed with an empty list
|
||||
// Temp vars are needed to hold values.
|
||||
let mut tmp_v_seeds: Vec<&[u8]> = vseeds.iter().map(|x| &x[..]).collect();
|
||||
let (_, bump_seed) = Pubkey::find_program_address(&tmp_v_seeds[..], ctx.program_id);
|
||||
let bsr = [&[bump_seed][..]];
|
||||
tmp_v_seeds.extend(bsr);
|
||||
let sig_seeds = &[&tmp_v_seeds[..]][..];
|
||||
|
||||
// allocate space
|
||||
let allocate_ix = system_instruction::allocate(pubkey, size as u64);
|
||||
invoke_signed(&allocate_ix, ctx.accounts, sig_seeds)?;
|
||||
|
||||
// assign ownership
|
||||
let assign_ix = system_instruction::assign(pubkey, ctx.program_id);
|
||||
invoke_signed(&assign_ix, ctx.accounts, sig_seeds)?;
|
||||
Ok(())
|
||||
}
|
|
@ -24,11 +24,25 @@ impl Owned for Config {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Temp test account data. If needed.
|
||||
#[derive(Default, Clone, Copy, BorshDeserialize, BorshSerialize)]
|
||||
pub struct TestStruct {
|
||||
}
|
||||
|
||||
impl Owned for TestStruct {
|
||||
fn owner(&self) -> AccountOwner {
|
||||
AccountOwner::This
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// icco sale state. Writeable in init, seal, abort.
|
||||
#[derive(Default, Clone, Copy, BorshDeserialize, BorshSerialize, Serialize, Deserialize)]
|
||||
/// Only static sizing is working well in here, so 256 is preallocated.
|
||||
//#[derive(Clone, Copy, BorshDeserialize, BorshSerialize, Serialize, Deserialize)]
|
||||
#[derive(Default, Clone, Copy, BorshDeserialize, BorshSerialize)]
|
||||
pub struct SaleState {
|
||||
pub is_sealed: bool,
|
||||
pub is_aborted: bool,
|
||||
}
|
||||
|
||||
impl Owned for SaleState {
|
||||
|
@ -37,7 +51,6 @@ impl Owned for SaleState {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// icco contribution state. Writeable in contribute, redeem, refund.
|
||||
#[derive(Default, Clone, Copy, BorshDeserialize, BorshSerialize, Serialize, Deserialize)]
|
||||
pub struct ContributionState {
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
instructions::{
|
||||
create_icco_sale_custody_account,
|
||||
get_icco_sale_custody_account_address,
|
||||
// get_test_account_address,
|
||||
get_icco_state_address,
|
||||
init_icco_sale,
|
||||
abort_icco_sale,
|
||||
|
@ -151,6 +152,13 @@ pub fn vaa_address(bridge_id: String, vaa: Vec<u8>) -> Vec<u8> {
|
|||
message_key.to_bytes().to_vec()
|
||||
}
|
||||
|
||||
/*
|
||||
#[wasm_bindgen]
|
||||
pub fn test_account_address(program_id: String, sale_id: u64) -> Pubkey {
|
||||
get_test_account_address (Pubkey::from_str(program_id.as_str()).unwrap(), sale_id as u128)
|
||||
}
|
||||
*/
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn icco_state_address(program_id: String, sale_id: u64) -> Pubkey {
|
||||
get_icco_state_address (Pubkey::from_str(program_id.as_str()).unwrap(), sale_id as u128)
|
||||
|
|
Loading…
Reference in New Issue