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%
1import Foundation23public struct CompiledKeyMeta {4 public var isSigner: Bool5 public var isWritable: Bool6 public var isInvoked: Bool78 public init(isSigner: Bool, isWritable: Bool, isInvoked: Bool) {9 self.isSigner = isSigner10 self.isWritable = isWritable11 self.isInvoked = isInvoked12 }13}1415public typealias KeyMetaMap = [String: CompiledKeyMeta]1617public struct CompiledKeys {18 public var payer: PublicKey19 public var keyMetaMap: KeyMetaMap2021 public init(payer: PublicKey, keyMetaMap: [String: CompiledKeyMeta]) {22 self.payer = payer23 self.keyMetaMap = keyMetaMap24 }2526 public mutating func extractTableLookup(lookupTable: AddressLookupTableAccount) throws -> (MessageAddressTableLookup, AccountKeysFromLookups)? {27 let (writableIndexes, drainedWritableKeys) = try drainKeysFoundInLookupTable(28 lookupTableEntries: lookupTable.state.addresses29 ) { keyMeta in30 !keyMeta.isSigner && !keyMeta.isInvoked && keyMeta.isWritable31 }3233 let (readonlyIndexes, drainedReadonlyKeys) = try drainKeysFoundInLookupTable(34 lookupTableEntries: lookupTable.state.addresses35 ) { keyMeta in36 !keyMeta.isSigner && !keyMeta.isInvoked && !keyMeta.isWritable37 }3839 if writableIndexes.count == 0, readonlyIndexes.count == 0 {40 return nil41 }4243 return (44 .init(45 accountKey: lookupTable.key,46 writableIndexes: writableIndexes,47 readonlyIndexes: readonlyIndexes48 ),49 .init(50 readonly: drainedReadonlyKeys,51 writable: drainedWritableKeys52 )53 )54 }5556 internal mutating func drainKeysFoundInLookupTable(57 lookupTableEntries: [PublicKey],58 keyMetaFilter: (CompiledKeyMeta) -> Bool59 ) throws -> ([UInt8], [PublicKey]) {60 var lookupTableIndexes: [UInt8] = []61 var drainedKeys: [PublicKey] = []6263 for (address, keyMeta) in keyMetaMap {64 if keyMetaFilter(keyMeta) {65 let key = try PublicKey(string: address)66 let lookupTableIndex = lookupTableEntries.firstIndex(of: key)67 if let lookupTableIndex = lookupTableIndex {68 lookupTableIndexes.append(UInt8(lookupTableIndex))69 drainedKeys.append(key)70 keyMetaMap.removeValue(forKey: address)71 }72 }73 }7475 return (lookupTableIndexes, drainedKeys)76 }7778 func getMessageComponents() -> (MessageHeader, [PublicKey]) {79 let writableSigners = keyMetaMap.filter { _, meta in80 meta.isSigner && meta.isWritable81 }8283 let readonlySigners = keyMetaMap.filter { _, meta in84 meta.isSigner && !meta.isWritable85 }8687 let writableNonSigners = keyMetaMap.filter { _, meta in88 !meta.isSigner && meta.isWritable89 }9091 let readonlyNonSigners = keyMetaMap.filter { _, meta in92 !meta.isSigner && !meta.isWritable93 }9495 let header: MessageHeader = .init(96 numRequiredSignatures: writableSigners.count + readonlySigners.count,97 numReadonlySignedAccounts: readonlySigners.count,98 numReadonlyUnsignedAccounts: readonlyNonSigners.count99 )100101 var staticAccountKeys: [PublicKey] = []102 staticAccountKeys.append(contentsOf: writableSigners.map(\.key).map { try! PublicKey(string: $0) })103 staticAccountKeys.append(contentsOf: readonlySigners.map(\.key).map { try! PublicKey(string: $0) })104 staticAccountKeys.append(contentsOf: writableNonSigners.map(\.key).map { try! PublicKey(string: $0) })105 staticAccountKeys.append(contentsOf: readonlyNonSigners.map(\.key).map { try! PublicKey(string: $0) })106107 return (header, staticAccountKeys)108 }109110 static func compile(instructions: [TransactionInstruction], payer: PublicKey) -> Self {111 var keyMetaMap: KeyMetaMap = .init()112 var getOrInsertDefault: (PublicKey, (inout CompiledKeyMeta) -> Void) -> CompiledKeyMeta = { pubKey, callback in113 let address = pubKey.base58EncodedString114 if var keyMeta = keyMetaMap[address] {115 callback(&keyMeta)116 keyMetaMap[address] = keyMeta117 return keyMeta118 } else {119 var keyMeta = CompiledKeyMeta(120 isSigner: false,121 isWritable: false,122 isInvoked: false123 )124 callback(&keyMeta)125 keyMetaMap[address] = keyMeta126 return keyMeta127 }128 }129130 _ = getOrInsertDefault(payer) { meta in131 meta.isSigner = true132 meta.isWritable = true133 }134135 for ix in instructions {136 _ = getOrInsertDefault(ix.programId) { meta in meta.isInvoked = true }137 for accountMeta in ix.keys {138 _ = getOrInsertDefault(accountMeta.publicKey) { meta in139 meta.isSigner = meta.isSigner || accountMeta.isSigner140 meta.isWritable = meta.isWritable || accountMeta.isWritable141 }142 }143 }144145 return .init(payer: payer, keyMetaMap: keyMetaMap)146 }147}148