SPB Git

spb/os-vault Public

Self-custody, multi-chain crypto wallet for macOS. One recovery phrase, six chain families, zero API keys — nothing leaves your Mac.

Swift 96% Shell 3.4% Makefile 0.6%
4.6 KB · 126 lines swift
Raw Blame History
1import Foundation23public extension SolanaBlockchainClient {4    /// Prepare instructions for creating WSOL account and close it after finishing transaction5    /// to return funds back to native SOL account6    /// - Parameters:7    ///   - owner: The owner of new WSOL account8    ///   - amount: The initial amount in Lamports to transfer to the new WSOL account9    ///   - payer: The payer of the transaction (usually the owner)10    ///   - mre: The min rent exemption (leave it nil if there is no pre-defined)11    /// - Returns: AccountInstructions that contains needed instructions, signers, .etc12    func prepareCreatingWSOLAccountAndCloseWhenDone(13        from owner: PublicKey,14        amount: Lamports,15        payer: PublicKey,16        minRentExemption: Lamports17    ) async throws -> AccountInstructions {18        let newAccount = try await KeyPair(network: apiClient.endpoint.network)1920        return .init(21            account: newAccount.publicKey,22            instructions: [23                SystemProgram.createAccountInstruction(24                    from: owner,25                    toNewPubkey: newAccount.publicKey,26                    lamports: amount + minRentExemption,27                    space: TokenAccountState.BUFFER_LENGTH,28                    programId: TokenProgram.id29                ),30                TokenProgram.initializeAccountInstruction(31                    account: newAccount.publicKey,32                    mint: .wrappedSOLMint,33                    owner: payer34                ),35            ],36            cleanupInstructions: [37                TokenProgram.closeAccountInstruction(38                    account: newAccount.publicKey,39                    destination: payer,40                    owner: payer41                ),42            ],43            signers: [44                newAccount,45            ],46            secretKey: newAccount.secretKey47        )48    }4950    /// Prepare instructions for creating associated token account and close if needed51    /// - Parameters:52    ///   - owner: The owner of new WSOL account53    ///   - mint: The mint of ther token54    ///   - feePayer: The payer of the transaction (usually the owner)55    ///   - closeAfterward: close after done or not56    /// - Returns: AccountInstructions that contains needed instructions, signers, .etc57    func prepareForCreatingAssociatedTokenAccount(58        owner: PublicKey,59        mint: PublicKey,60        tokenProgramId: PublicKey,61        feePayer: PublicKey,62        closeAfterward: Bool63    ) async throws -> AccountInstructions {64        let associatedAddress = try PublicKey.associatedTokenAddress(65            walletAddress: owner,66            tokenMintAddress: mint,67            tokenProgramId: tokenProgramId68        )6970        let isAssociatedTokenAddressRegistered: Bool71        do {72            let info: BufferInfo<TokenAccountState>? = try await apiClient73                .getAccountInfo(account: associatedAddress.base58EncodedString)74            if PublicKey.isSPLTokenProgram(info?.owner),75               info?.data.owner == owner76            {77                isAssociatedTokenAddressRegistered = true78            } else {79                throw BlockchainClientError.other("Associated token account is belong to another user")80            }81        } catch {82            if error.isEqualTo(.couldNotRetrieveAccountInfo) {83                isAssociatedTokenAddressRegistered = false84            } else {85                throw error86            }87        }8889        // cleanup intructions90        var cleanupInstructions = [TransactionInstruction]()91        if closeAfterward {92            cleanupInstructions = [93                TokenProgram.closeAccountInstruction(94                    account: associatedAddress,95                    destination: owner,96                    owner: owner97                ),98            ]99        }100101        // if associated address is registered, there is no need to creating it again102        if isAssociatedTokenAddressRegistered {103            return .init(104                account: associatedAddress,105                cleanupInstructions: []106            )107        }108109        // else create associated address110        return try .init(111            account: associatedAddress,112            instructions: [113                AssociatedTokenProgram114                    .createAssociatedTokenAccountInstruction(115                        mint: mint,116                        owner: owner,117                        payer: feePayer,118                        tokenProgramId: tokenProgramId119                    ),120            ],121            cleanupInstructions: cleanupInstructions,122            newWalletPubkey: associatedAddress.base58EncodedString123        )124    }125}126