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%
1//2// Hex.swift3// OS Vault4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//89import Foundation10import BigInt1112/// Minimal hex helpers for JSON-RPC quantities and calldata.13public enum Hex {1415 public static func quantity(_ value: BigUInt) -> String {16 "0x" + String(value, radix: 16)17 }1819 public static func toBigUInt(_ hex: String) -> BigUInt? {20 let stripped = hex.hasPrefix("0x") ? String(hex.dropFirst(2)) : hex21 if stripped.isEmpty { return 0 }22 return BigUInt(stripped, radix: 16)23 }2425 public static func data(_ hex: String) -> Data? {26 var stripped = hex.hasPrefix("0x") ? String(hex.dropFirst(2)) : hex27 if stripped.count % 2 != 0 { stripped = "0" + stripped }28 var out = Data(capacity: stripped.count / 2)29 var index = stripped.startIndex30 while index < stripped.endIndex {31 let next = stripped.index(index, offsetBy: 2)32 guard let byte = UInt8(stripped[index..<next], radix: 16) else { return nil }33 out.append(byte)34 index = next35 }36 return out37 }3839 public static func string(_ data: Data) -> String {40 "0x" + data.map { String(format: "%02x", $0) }.joined()41 }4243 /// Left-pads to a 32-byte ABI word.44 public static func abiWord(_ data: Data) -> Data {45 if data.count >= 32 { return data.suffix(32) }46 return Data(repeating: 0, count: 32 - data.count) + data47 }4849 public static func abiWord(_ value: BigUInt) -> Data {50 abiWord(value.serialize())51 }5253 /// ERC-20 `transfer(address,uint256)` calldata.54 public static func erc20TransferData(to recipient: String, amount: BigUInt) -> Data? {55 guard let addressData = data(recipient), addressData.count == 20 else { return nil }56 var calldata = Data([0xa9, 0x05, 0x9c, 0xbb])57 calldata.append(abiWord(addressData))58 calldata.append(abiWord(amount))59 return calldata60 }6162 /// ERC-20 `balanceOf(address)` calldata.63 public static func erc20BalanceOfData(owner: String) -> Data? {64 guard let addressData = data(owner), addressData.count == 20 else { return nil }65 var calldata = Data([0x70, 0xa0, 0x82, 0x31])66 calldata.append(abiWord(addressData))67 return calldata68 }69}70