Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"dependencies": {
"@coral-xyz/anchor": "0.29.0",
"@inquirer/prompts": "7.9.0",
"@ledgerhq/hw-app-solana": "7.10.4",
"@ledgerhq/hw-transport-node-hid": "6.33.4",
"@metadaoproject/programs": "./sdk",
"@metaplex-foundation/mpl-token-metadata": "3.4.0",
"@metaplex-foundation/umi": "0.9.2",
Expand Down
6 changes: 6 additions & 0 deletions scripts/assets/LASO/LASO.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "Laso Finance",
"symbol": "LASO",
"description": "Spend your crypto privately. No ID upload. Privacy for humans. Frictionless for agents.",
"image": "https://raw.githubusercontent.com/metaDAOproject/programs/refs/heads/develop/scripts/assets/LASO/LASO.png"
}
Binary file added scripts/assets/LASO/LASO.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions scripts/utils/ledger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as TransportNodeHidModule from "@ledgerhq/hw-transport-node-hid";
import * as SolanaAppModule from "@ledgerhq/hw-app-solana";
import { PublicKey } from "@solana/web3.js";

const TransportNodeHid =
(TransportNodeHidModule as any).default?.default ||
(TransportNodeHidModule as any).default;
const SolanaApp =
(SolanaAppModule as any).default?.default || (SolanaAppModule as any).default;

export const LEDGER_DERIVATION_PATH = "44'/501'/0'";

export async function connectLedger(): Promise<{
solana: any;
publicKey: PublicKey;
}> {
console.log(" Connecting to Ledger device...");
console.log(" Please unlock your Ledger and open the Solana app.");

const transport = await TransportNodeHid.open("");
const solana = new SolanaApp(transport);

const { address } = await solana.getAddress(LEDGER_DERIVATION_PATH);
const publicKey = new PublicKey(Buffer.from(address));

console.log(" Connected! Ledger address:", publicKey.toBase58());
return { solana, publicKey };
}
33 changes: 32 additions & 1 deletion scripts/utils/squads.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PublicKey } from "@solana/web3.js";
import { PERMISSIONLESS_ACCOUNT } from "@metadaoproject/programs";
import { PublicKey, TransactionMessage } from "@solana/web3.js";
import * as multisig from "@sqds/multisig";

// Returns the multisig, spending limit and 0th vault pda for a given dao address
Expand Down Expand Up @@ -31,3 +32,33 @@ export const getSquadsPdasFromDao = async (
vaultPda,
};
};

export const createSquadsVaultTxAndProposal = async (
squadsMultisig: PublicKey,
transactionIndex: bigint,
transactionMessage: TransactionMessage,
payer: PublicKey,
) => {
const vaultTxCreateIx = multisig.instructions.vaultTransactionCreate({
multisigPda: squadsMultisig,
transactionIndex: transactionIndex,
creator: PERMISSIONLESS_ACCOUNT.publicKey,
rentPayer: payer,
vaultIndex: 0,
ephemeralSigners: 0,
transactionMessage,
});

const proposalCreateIx = multisig.instructions.proposalCreate({
multisigPda: squadsMultisig,
transactionIndex: transactionIndex,
creator: PERMISSIONLESS_ACCOUNT.publicKey,
rentPayer: payer,
isDraft: false,
});

return {
vaultTxCreateIx,
proposalCreateIx,
};
};
92 changes: 92 additions & 0 deletions scripts/v0.7/laso/complete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as anchor from "@coral-xyz/anchor";
import {
LaunchpadClient,
getLaunchAddr,
} from "@metadaoproject/programs/launchpad/v0.7";
import {
PublicKey,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { createLookupTableForTransaction } from "../../utils/utils.js";
import { token } from "@coral-xyz/anchor/dist/cjs/utils/index.js";
import { TOKEN_SEED } from "./constants.js";

const provider = anchor.AnchorProvider.env();
const payer = provider.wallet["payer"];

const launchpad: LaunchpadClient = LaunchpadClient.createClient({ provider });

export const completeLaunch = async () => {
// TODO: BEFORE RUNNING YOU NEED TO APPROVE THE FUNDING RECORDS
// SCRIPT MUST BE CREATED
const TOKEN = await PublicKey.createWithSeed(
payer.publicKey,
TOKEN_SEED,
token.TOKEN_PROGRAM_ID,
);
console.log("Token address:", TOKEN.toBase58());

const [launch] = getLaunchAddr(undefined, TOKEN);

if (launch === undefined) {
throw new Error(
"LAUNCH_TO_COMPLETE is not set. Please set it in the script.",
);
}

let launchAccount = await launchpad.fetchLaunch(launch);

const tx = await launchpad
.completeLaunchIx({
launch: launch,
baseMint: launchAccount.baseMint,
launchAuthority: payer.publicKey,
})
.transaction();

const LUT = await createLookupTableForTransaction(
tx,
payer,
provider.connection,
);

const blockhash = (await provider.connection.getLatestBlockhash()).blockhash;

const message = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions: tx.instructions,
}).compileToV0Message([LUT]);

const vtx = new VersionedTransaction(message);
vtx.sign([payer]);

const completeTxHash = await provider.connection.sendTransaction(vtx);

console.log(`Complete launch transaction sent: ${completeTxHash}`);

console.log("Launch completed successfully!");

console.log("Setting up performance package...");

// Refresh launch account to get the updated base mint
launchAccount = await launchpad.fetchLaunch(launch);

// TODO: Review this as we will want to do this manually..
const initializePerformancePackageTxHash = await launchpad
.initializePerformancePackageIx({
launch: launch,
baseMint: launchAccount.baseMint,
payer: payer.publicKey,
})
.rpc();

console.log(
`Initialize performance package transaction sent: ${initializePerformancePackageTxHash}`,
);

console.log("Performance package set up successfully!");
};

completeLaunch().catch(console.error);
33 changes: 33 additions & 0 deletions scripts/v0.7/laso/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { PublicKey } from "@solana/web3.js";

// Token Details
export const TOKEN_SEED = "7VpRX8sqCTEmdAa9";

// Team Config Details
export const TEAM_ADDRESS = new PublicKey(
"82MdwSmh7JEK9cywZusE27m8zwbhmkR9Bs38jQoAwwCc",

Check warning on line 8 in scripts/v0.7/laso/constants.ts

View workflow job for this annotation

GitHub Actions / repository-guard

Hardcoded Solana address literal: + "82MdwSmh7JEK9cywZusE27m8zwbhmkR9Bs38jQoAwwCc",
); // Laso team squads address

export const SPENDING_MEMBERS = [
new PublicKey("4XMTsBivE5V73ScmuChGVLS6oF8MFb2P3fvR3gt9So9J"),

Check warning on line 12 in scripts/v0.7/laso/constants.ts

View workflow job for this annotation

GitHub Actions / repository-guard

Hardcoded Solana address literal: + new PublicKey("4XMTsBivE5V73ScmuChGVLS6oF8MFb2P3fvR3gt9So9J"),
];
// Even without a performance package, defaults need to be set
export const PERFORMANCE_PACKAGE_GRANTEE = new PublicKey(
"11111111111111111111111111111111", // Placeholder for no performance package

Check warning on line 16 in scripts/v0.7/laso/constants.ts

View workflow job for this annotation

GitHub Actions / repository-guard

Hardcoded Solana address literal: + "11111111111111111111111111111111", // Placeholder for no performance package
);

// Amount Details
export const MIN_GOAL = 750_000; // 750K USDC
export const SPENDING_LIMIT = 50_000; // 50k USDC
export const PERFORMANCE_PACKAGE_TOKEN_AMOUNT = 1; // 1 LASO
export const PERFORMANCE_PACKAGE_UNLOCK_MONTHS = 24; // 24 months
export const ADDITIONAL_CARVEOUT = 27_100_000; // 27.1M LASO
export const ADDITIONAL_CARVEOUT_RECIPIENT = new PublicKey(
"91PL1BRM2jGbt6jxv56hhkAFbvsHMHLirMXDQCQcvY92",

Check warning on line 26 in scripts/v0.7/laso/constants.ts

View workflow job for this annotation

GitHub Actions / repository-guard

Hardcoded Solana address literal: + "91PL1BRM2jGbt6jxv56hhkAFbvsHMHLirMXDQCQcvY92",
); // Established Multisig For Laso Launch
// 2/3 Kollan Proph3t Pileks

export const TOKEN_NAME = "Laso Finance";
export const TOKEN_SYMBOL = "LASO";
export const TOKEN_URI =
"https://raw.githubusercontent.com/metaDAOproject/programs/refs/heads/develop/scripts/assets/LASO/LASO.json";
74 changes: 74 additions & 0 deletions scripts/v0.7/laso/end.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as anchor from "@coral-xyz/anchor";
import {
LaunchpadClient,
getLaunchAddr,
} from "@metadaoproject/programs/launchpad/v0.7";
import { ComputeBudgetProgram, PublicKey, Transaction } from "@solana/web3.js";
import * as token from "@solana/spl-token";
import { TOKEN_SEED } from "./constants.js";

const provider = anchor.AnchorProvider.env();
const payer = provider.wallet["payer"];

const launchpad: LaunchpadClient = LaunchpadClient.createClient({ provider });

export const end = async () => {
const TOKEN = await PublicKey.createWithSeed(
payer.publicKey,
TOKEN_SEED,
token.TOKEN_PROGRAM_ID,
);
console.log("Token address:", TOKEN.toBase58());

const [launch] = getLaunchAddr(undefined, TOKEN);

const closeLaunchIx = await launchpad
.closeLaunchIx({
launch,
})
.instruction();

// Build transaction without compute budget first
const tx = new Transaction().add(closeLaunchIx);

const { blockhash } = await provider.connection.getLatestBlockhash();
tx.recentBlockhash = blockhash;
tx.feePayer = payer.publicKey;

// Simulate transaction to get compute units used
tx.sign(payer);
const simulation = await provider.connection.simulateTransaction(tx);

if (simulation.value.err) {
console.error("Transaction simulation failed:", simulation.value.err);
throw new Error(
`Simulation failed: ${JSON.stringify(simulation.value.err)}`,
);
}

const computeUnitsUsed = simulation.value.unitsConsumed || 200_000;
// Add 20% buffer to the compute units
const computeUnitsWithBuffer = Math.floor(computeUnitsUsed * 1.2);

console.log(`Simulated compute units: ${computeUnitsUsed}`);
console.log(`Setting compute unit limit: ${computeUnitsWithBuffer}`);

// Rebuild transaction with compute budget
const finalTx = new Transaction().add(
ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnitsWithBuffer }),
closeLaunchIx,
);

finalTx.recentBlockhash = blockhash;
finalTx.feePayer = payer.publicKey;
finalTx.sign(payer);

const txHash = await provider.connection.sendRawTransaction(
finalTx.serialize(),
);
await provider.connection.confirmTransaction(txHash, "confirmed");

console.log("Launch closed", txHash);
};

end().catch(console.error);
Loading
Loading