@@ -30,6 +30,12 @@ import {
3030import { pythOracleProgram } from "@pythnetwork/client" ;
3131import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider" ;
3232import { LedgerNodeWallet } from "./ledger" ;
33+ import {
34+ createTransferInstruction ,
35+ getAssociatedTokenAddress ,
36+ getMint ,
37+ } from "@solana/spl-token" ;
38+ import { TOKEN_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/utils/token" ;
3339
3440export async function loadHotWalletOrLedger (
3541 wallet : string ,
@@ -299,4 +305,59 @@ mutlisigCommand("approve", "Approve a transaction sitting in the multisig")
299305 await squad . approveTransaction ( transaction ) ;
300306 } ) ;
301307
308+ mutlisigCommand ( "propose-token-transfer" , "Propose token transfer" )
309+ . requiredOption ( "-a, --amount <number>" , "amount in dollars" )
310+ . requiredOption ( "-d, --destination <pubkey>" , "destination address" )
311+ . option (
312+ "-m --mint <pubkey>" ,
313+ "mint to transfer" ,
314+ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" // default value is solana mainnet USDC SPL
315+ )
316+ . action ( async ( options : any ) => {
317+ const wallet = await loadHotWalletOrLedger (
318+ options . wallet ,
319+ options . ledgerDerivationAccount ,
320+ options . ledgerDerivationChange
321+ ) ;
322+
323+ const cluster : PythCluster = options . cluster ;
324+ const destination : PublicKey = new PublicKey ( options . destination ) ;
325+ const mint : PublicKey = new PublicKey ( options . mint ) ;
326+ const vault : PublicKey = new PublicKey ( options . vault ) ;
327+ const amount : number = options . amount ;
328+
329+ const squad = SquadsMesh . endpoint ( getPythClusterApiUrl ( cluster ) , wallet ) ;
330+ const msAccount = await squad . getMultisig ( vault ) ;
331+ const vaultAuthority = squad . getAuthorityPDA (
332+ msAccount . publicKey ,
333+ msAccount . authorityIndex
334+ ) ;
335+
336+ const mintAccount = await getMint (
337+ squad . connection ,
338+ mint ,
339+ undefined ,
340+ TOKEN_PROGRAM_ID
341+ ) ;
342+ const sourceTokenAccount = await getAssociatedTokenAddress (
343+ mint ,
344+ vaultAuthority ,
345+ true
346+ ) ;
347+ const destinationTokenAccount = await getAssociatedTokenAddress (
348+ mint ,
349+ destination
350+ ) ;
351+
352+ const proposalInstruction : TransactionInstruction =
353+ createTransferInstruction (
354+ sourceTokenAccount ,
355+ destinationTokenAccount ,
356+ vaultAuthority ,
357+ BigInt ( amount ) * BigInt ( 10 ) ** BigInt ( mintAccount . decimals )
358+ ) ;
359+
360+ await proposeInstructions ( squad , vault , [ proposalInstruction ] , false ) ;
361+ } ) ;
362+
302363program . parse ( ) ;
0 commit comments