OS Vault 1.0.0 — self-custody multi-chain wallet for macOS
One BIP-39 phrase drives six chain families: 11 EVM chains, Bitcoin (BIP-84 via bdk-swift), Solana (SPL), Tron (TRC-20 via vendored Trust wallet-core), XRP Ledger (RLUSD trustlines) and TON (jettons). Keys are sealed in OS Vault's own PBKDF2→AES-GCM vault (no Keychain); every send re-derives and discards the key. All endpoints keyless with failover; 32 unit tests incl. BIP-39/BIP-84 vectors and cross-stack derivation checks; signed, notarized, stapled release pipeline with DMG. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 142 changed files with +20,001 and −0
added
.gitignore
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +# Build products | |
| 2 | +.build/ | |
| 3 | +dist/ | |
| 4 | +*.xcodeproj | |
| 5 | + | |
| 6 | +# Vendored binary too large for git (270 MB) — regenerate with | |
| 7 | +# scripts/vendor-walletcore.sh | |
| 8 | +vendor/WalletCoreSPM/WalletCoreCommon.xcframework/ | |
| 9 | + | |
| 10 | +# macOS | |
| 11 | +.DS_Store | |
| 12 | + | |
| 13 | +# Local state | |
| 14 | +*.sqlite | |
added
CLAUDE.md
+157 −0
@@ -0,0 +1,157 @@ | ||
| 1 | +# CLAUDE.md — Zyquo Wallet | |
| 2 | + | |
| 3 | +## Project Overview | |
| 4 | + | |
| 5 | +**Zyquo Wallet** is a native **macOS** self-custody stablecoin wallet built in **Swift + SwiftUI**. It manages **real on-chain USDC** on **Base** (Ethereum L2 by Coinbase — chosen for sub-cent gas fees and native Circle-issued USDC). | |
| 6 | + | |
| 7 | +This is NOT a mock/demo app. Every feature must work against a real blockchain: | |
| 8 | +1. Real HD wallet creation (BIP-39 mnemonic → secp256k1 keys) | |
| 9 | +2. Receive USDC (real address + QR code) | |
| 10 | +3. Send USDC (real signed ERC-20 transfers broadcast via JSON-RPC) | |
| 11 | + | |
| 12 | +**Development rule: build and test everything on Base Sepolia testnet first. Mainnet support is enabled last, behind an explicit network switch.** | |
| 13 | + | |
| 14 | +--- | |
| 15 | + | |
| 16 | +## Tech Stack | |
| 17 | + | |
| 18 | +| Layer | Choice | | |
| 19 | +|---|---| | |
| 20 | +| Language | Swift 5.10+ (strict concurrency where possible) | | |
| 21 | +| UI | SwiftUI, macOS 14+ target | | |
| 22 | +| Project | Xcode project, dependencies via Swift Package Manager only | | |
| 23 | +| Web3 | `web3swift` (https://github.com/web3swift-team/web3swift) — actively maintained, macOS support, BIP-39/BIP-32, ERC-20, EIP-1559 | | |
| 24 | +| QR codes | CoreImage (`CIQRCodeGenerator`) — no extra dependency | | |
| 25 | +| Key storage | macOS Keychain (Security framework) | | |
| 26 | +| Persistence | UserDefaults for settings; no database needed for v1 (history read from chain/explorer API) | | |
| 27 | + | |
| 28 | +If `web3swift` causes build issues on macOS, fallback is `argentlabs/web3.swift`. Never mix both. | |
| 29 | + | |
| 30 | +--- | |
| 31 | + | |
| 32 | +## Network Configuration (source of truth) | |
| 33 | + | |
| 34 | +```swift | |
| 35 | +enum Network { | |
| 36 | + case baseSepolia // DEFAULT during development | |
| 37 | + case baseMainnet | |
| 38 | +} | |
| 39 | +``` | |
| 40 | + | |
| 41 | +| | Base Sepolia (testnet) | Base Mainnet | | |
| 42 | +|---|---|---| | |
| 43 | +| Chain ID | 84532 | 8453 | | |
| 44 | +| RPC (dev) | https://sepolia.base.org | https://mainnet.base.org | | |
| 45 | +| USDC contract | `0x036CbD53842c5426634e7929541eC2318f3dCF7e` | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | | |
| 46 | +| Explorer | https://sepolia.basescan.org | https://basescan.org | | |
| 47 | +| Faucets | Circle faucet (https://faucet.circle.com — 20 USDC / 2h) + Base Sepolia ETH faucet for gas | — | | |
| 48 | + | |
| 49 | +- **USDC has 6 decimals.** Always convert with `BigUInt` / decimal math — never `Double`. 1 USDC = 1_000_000 base units. | |
| 50 | +- Public RPCs are fine for dev. For production, make the RPC URL configurable (Alchemy/QuickNode) via Settings — but never require an API key to run the app. | |
| 51 | +- Gas is paid in **ETH**, not USDC. The UI must clearly warn when the ETH balance is too low to send. | |
| 52 | + | |
| 53 | +--- | |
| 54 | + | |
| 55 | +## Architecture | |
| 56 | + | |
| 57 | +MVVM + service layer. Keep views dumb; all blockchain logic lives in services. | |
| 58 | + | |
| 59 | +``` | |
| 60 | +ZyquoWallet/ | |
| 61 | +├── App/ ZyquoWalletApp.swift, AppState (ObservableObject / @Observable) | |
| 62 | +├── Models/ Wallet, Transaction, Network, TokenAmount | |
| 63 | +├── Services/ | |
| 64 | +│ ├── KeyManager.swift // mnemonic gen/import, keystore, Keychain I/O | |
| 65 | +│ ├── WalletService.swift // address derivation, wallet lifecycle | |
| 66 | +│ ├── RPCService.swift // web3 provider, network switching | |
| 67 | +│ ├── BalanceService.swift // ETH + USDC balances, polling every 15s | |
| 68 | +│ └── TransactionService.swift// build, estimate gas, sign, send, track receipt | |
| 69 | +├── ViewModels/ OnboardingVM, HomeVM, SendVM, ReceiveVM, SettingsVM | |
| 70 | +├── Views/ | |
| 71 | +│ ├── Onboarding/ Welcome, CreateWallet (show + verify mnemonic), ImportWallet | |
| 72 | +│ ├── Home/ Balance card, tx list, Send/Receive buttons | |
| 73 | +│ ├── Send/ recipient + amount + gas preview + confirm sheet | |
| 74 | +│ ├── Receive/ address display, QR, copy button | |
| 75 | +│ └── Settings/ network switch, RPC override, export seed (auth-gated), reset | |
| 76 | +└── Utils/ formatting, address validation (EIP-55), errors | |
| 77 | +``` | |
| 78 | + | |
| 79 | +- Use `async/await` everywhere; wrap web3swift callbacks if needed. | |
| 80 | +- One `AppState` injected via `.environment`; services are protocol-backed for testability. | |
| 81 | +- Every service method that touches the network returns typed errors (`WalletError` enum), never `fatalError`. | |
| 82 | + | |
| 83 | +--- | |
| 84 | + | |
| 85 | +## Security Requirements (non-negotiable) | |
| 86 | + | |
| 87 | +1. **Mnemonic & private key never leave the device.** No analytics, no telemetry, no network calls except JSON-RPC and explorer API. | |
| 88 | +2. Store the mnemonic (or derived keystore) in **Keychain** with `kSecAttrAccessibleWhenUnlockedThisDeviceOnly`. Never in UserDefaults, files, or iCloud. | |
| 89 | +3. Gate seed export and every send behind **LocalAuthentication** (Touch ID / password). | |
| 90 | +4. **Never log** mnemonics, private keys, or signatures. Never put them in error messages. | |
| 91 | +5. Never hardcode keys, mnemonics, or API keys anywhere in the repo — including tests. Test wallets are generated at runtime. | |
| 92 | +6. Onboarding must force a **mnemonic backup verification** step (user re-enters 3 random words) before showing the wallet. | |
| 93 | +7. Validate recipient addresses: hex format + EIP-55 checksum. Warn (don't block) on all-lowercase addresses. | |
| 94 | +8. Enable **App Sandbox** (with network client entitlement) and **Hardened Runtime**. | |
| 95 | +9. Confirm screen before send must show: recipient, amount, network, estimated gas, and total — no one-tap sends. | |
| 96 | +10. If the clipboard is used for addresses, never auto-paste into the recipient field without user action (clipboard-hijack protection). | |
| 97 | + | |
| 98 | +--- | |
| 99 | + | |
| 100 | +## Feature Phases (implement in order, each must compile + pass tests) | |
| 101 | + | |
| 102 | +### Phase 1 — Wallet core | |
| 103 | +- Generate 12-word BIP-39 mnemonic, derive account at `m/44'/60'/0'/0/0` | |
| 104 | +- Import from mnemonic | |
| 105 | +- Persist via KeyManager/Keychain; app relaunch restores wallet | |
| 106 | +- Onboarding flow with backup verification | |
| 107 | + | |
| 108 | +### Phase 2 — Receive | |
| 109 | +- Show checksummed address, copy button, QR code (address only, no `ethereum:` URI needed for v1) | |
| 110 | + | |
| 111 | +### Phase 3 — Balances | |
| 112 | +- ETH balance (`eth_getBalance`) + USDC balance (`balanceOf(address)`) | |
| 113 | +- Poll every 15s while app is active; manual refresh; loading/error states | |
| 114 | + | |
| 115 | +### Phase 4 — Send USDC | |
| 116 | +- ERC-20 `transfer(to, amount)` with EIP-1559 fees | |
| 117 | +- Gas estimation shown in ETH + rough USD | |
| 118 | +- Sign locally, broadcast, then poll `eth_getTransactionReceipt` until confirmed | |
| 119 | +- Pending/confirmed/failed states surfaced in UI, link to BaseScan | |
| 120 | + | |
| 121 | +### Phase 5 — History & polish | |
| 122 | +- Transaction list from BaseScan API (USDC transfers in/out) with graceful fallback if API unavailable | |
| 123 | +- Network switcher (Sepolia ⇄ Mainnet) with a prominent "TESTNET" badge on Sepolia | |
| 124 | +- Settings: custom RPC, export seed (auth-gated), delete wallet (typed confirmation) | |
| 125 | + | |
| 126 | +--- | |
| 127 | + | |
| 128 | +## Build & Test Commands | |
| 129 | + | |
| 130 | +```bash | |
| 131 | +# Build | |
| 132 | +xcodebuild -scheme ZyquoWallet -destination 'platform=macOS' build | |
| 133 | + | |
| 134 | +# Tests | |
| 135 | +xcodebuild -scheme ZyquoWallet -destination 'platform=macOS' test | |
| 136 | +``` | |
| 137 | + | |
| 138 | +- Unit-test: mnemonic → address derivation (against known BIP-39 test vectors), USDC decimal conversion, address validation, amount formatting. | |
| 139 | +- Never write tests that send real mainnet funds. Network-dependent tests run against Base Sepolia and must be skippable offline. | |
| 140 | + | |
| 141 | +## Manual test checklist (Base Sepolia) | |
| 142 | +1. Create wallet → relaunch app → same address restored | |
| 143 | +2. Fund via Circle faucet (USDC) + Base faucet (ETH for gas) | |
| 144 | +3. Balance appears within one polling cycle | |
| 145 | +4. Send 1 USDC to a second test wallet → confirm on sepolia.basescan.org | |
| 146 | +5. Import that second wallet from mnemonic → balance matches | |
| 147 | + | |
| 148 | +--- | |
| 149 | + | |
| 150 | +## Conventions & Pitfalls | |
| 151 | + | |
| 152 | +- All amounts are `BigUInt` in base units internally; convert to display strings only at the UI edge. | |
| 153 | +- USDC = 6 decimals, ETH = 18 decimals. Mixing these up is the #1 bug source. | |
| 154 | +- Chain ID must match the selected network in every signed transaction (replay protection). | |
| 155 | +- Handle RPC failures with retry + user-visible error; the app must never crash on network errors. | |
| 156 | +- Comments and UI strings in English; French localization can come later via String Catalog. | |
| 157 | +- Small, focused commits per phase. Do not start a later phase before the earlier one builds and passes tests. | |
added
Makefile
+60 −0
@@ -0,0 +1,60 @@ | ||
| 1 | +# | |
| 2 | +# Makefile | |
| 3 | +# OS Vault | |
| 4 | +# | |
| 5 | +# Author: Simon-Pierre Boucher | |
| 6 | +# Mail: contact@spboucher.ai | |
| 7 | +# | |
| 8 | + | |
| 9 | +APP_NAME := OS Vault | |
| 10 | +EXEC_NAME := OSVault | |
| 11 | +BUNDLE_ID := com.zyquo.osvault | |
| 12 | +VERSION := 1.0.0 | |
| 13 | +BUILD_DIR := .build | |
| 14 | +DIST_DIR := dist | |
| 15 | +APP_BUNDLE := $(DIST_DIR)/$(APP_NAME).app | |
| 16 | +SIGN_IDENTITY := Developer ID Application: Simon-Pierre Boucher (3YM54G49SN) | |
| 17 | +NOTARY_PROFILE := MacLustr-Notarize | |
| 18 | + | |
| 19 | +.PHONY: build release-build test clean dev bundle-debug bundle-release run release | |
| 20 | + | |
| 21 | +build: | |
| 22 | + swift build | |
| 23 | + | |
| 24 | +release-build: | |
| 25 | + swift build -c release | |
| 26 | + | |
| 27 | +test: | |
| 28 | + swift test | |
| 29 | + | |
| 30 | +clean: | |
| 31 | + swift package clean | |
| 32 | + rm -rf $(DIST_DIR) | |
| 33 | + | |
| 34 | +# ── App bundle assembly ────────────────────────────────────────────────────── | |
| 35 | +# $(1) = built products dir (.build/debug or .build/release) | |
| 36 | +define assemble_bundle | |
| 37 | + rm -rf "$(APP_BUNDLE)" | |
| 38 | + mkdir -p "$(APP_BUNDLE)/Contents/MacOS" "$(APP_BUNDLE)/Contents/Resources" | |
| 39 | + cp "$(1)/$(EXEC_NAME)" "$(APP_BUNDLE)/Contents/MacOS/$(EXEC_NAME)" | |
| 40 | + cp Support/Info.plist "$(APP_BUNDLE)/Contents/Info.plist" | |
| 41 | + printf 'APPL????' > "$(APP_BUNDLE)/Contents/PkgInfo" | |
| 42 | + [ -f assets/icon/AppIcon.icns ] && cp assets/icon/AppIcon.icns "$(APP_BUNDLE)/Contents/Resources/AppIcon.icns" || true | |
| 43 | +endef | |
| 44 | + | |
| 45 | +bundle-debug: build | |
| 46 | + $(call assemble_bundle,$(BUILD_DIR)/debug) | |
| 47 | + codesign --force --deep --entitlements Support/entitlements.plist --sign - "$(APP_BUNDLE)" | |
| 48 | + | |
| 49 | +bundle-release: release-build | |
| 50 | + $(call assemble_bundle,$(BUILD_DIR)/release) | |
| 51 | + | |
| 52 | +# Debug bundle, ad-hoc signed, launched. | |
| 53 | +dev: bundle-debug | |
| 54 | + open "$(APP_BUNDLE)" | |
| 55 | + | |
| 56 | +run: dev | |
| 57 | + | |
| 58 | +# Signed, notarized, stapled release: scripts/release.sh | |
| 59 | +release: | |
| 60 | + scripts/release.sh | |
added
Package.resolved
+78 −0
@@ -0,0 +1,78 @@ | ||
| 1 | +{ | |
| 2 | + "originHash" : "a8d3a77901f33178ea03447308323e177a207103fb42a71c5911e627b913f154", | |
| 3 | + "pins" : [ | |
| 4 | + { | |
| 5 | + "identity" : "bdk-swift", | |
| 6 | + "kind" : "remoteSourceControl", | |
| 7 | + "location" : "https://github.com/bitcoindevkit/bdk-swift", | |
| 8 | + "state" : { | |
| 9 | + "revision" : "5bc9c3cddf203f6aa147d77364782bf095e4f84e", | |
| 10 | + "version" : "3.0.0" | |
| 11 | + } | |
| 12 | + }, | |
| 13 | + { | |
| 14 | + "identity" : "bigint", | |
| 15 | + "kind" : "remoteSourceControl", | |
| 16 | + "location" : "https://github.com/attaswift/BigInt.git", | |
| 17 | + "state" : { | |
| 18 | + "revision" : "793a7fac0bfc318e85994bf6900652e827aef33e", | |
| 19 | + "version" : "5.4.1" | |
| 20 | + } | |
| 21 | + }, | |
| 22 | + { | |
| 23 | + "identity" : "cryptoswift", | |
| 24 | + "kind" : "remoteSourceControl", | |
| 25 | + "location" : "https://github.com/krzyzanowskim/CryptoSwift.git", | |
| 26 | + "state" : { | |
| 27 | + "revision" : "039f56c5d7960f277087a0be51f5eb04ed0ec073", | |
| 28 | + "version" : "1.5.1" | |
| 29 | + } | |
| 30 | + }, | |
| 31 | + { | |
| 32 | + "identity" : "secp256k1.swift", | |
| 33 | + "kind" : "remoteSourceControl", | |
| 34 | + "location" : "https://github.com/GigaBitcoin/secp256k1.swift", | |
| 35 | + "state" : { | |
| 36 | + "revision" : "48fb20fce4ca3aad89180448a127d5bc16f0e44c", | |
| 37 | + "version" : "0.10.0" | |
| 38 | + } | |
| 39 | + }, | |
| 40 | + { | |
| 41 | + "identity" : "swift-protobuf", | |
| 42 | + "kind" : "remoteSourceControl", | |
| 43 | + "location" : "https://github.com/apple/swift-protobuf.git", | |
| 44 | + "state" : { | |
| 45 | + "revision" : "55d7a1cc5666b85c13464aea1c4b4a90feccb4c8", | |
| 46 | + "version" : "1.38.1" | |
| 47 | + } | |
| 48 | + }, | |
| 49 | + { | |
| 50 | + "identity" : "task-retrying-swift", | |
| 51 | + "kind" : "remoteSourceControl", | |
| 52 | + "location" : "https://github.com/bigearsenal/task-retrying-swift.git", | |
| 53 | + "state" : { | |
| 54 | + "revision" : "208f1e8dfa93022a7d39ab5b334d5f43a934d4b1", | |
| 55 | + "version" : "2.0.0" | |
| 56 | + } | |
| 57 | + }, | |
| 58 | + { | |
| 59 | + "identity" : "tweetnacl-swiftwrap", | |
| 60 | + "kind" : "remoteSourceControl", | |
| 61 | + "location" : "https://github.com/bitmark-inc/tweetnacl-swiftwrap.git", | |
| 62 | + "state" : { | |
| 63 | + "revision" : "f8fd111642bf2336b11ef9ea828510693106e954", | |
| 64 | + "version" : "1.1.0" | |
| 65 | + } | |
| 66 | + }, | |
| 67 | + { | |
| 68 | + "identity" : "web3swift", | |
| 69 | + "kind" : "remoteSourceControl", | |
| 70 | + "location" : "https://github.com/web3swift-team/web3swift.git", | |
| 71 | + "state" : { | |
| 72 | + "revision" : "b9c771bf3b94983d2f9b22096b4a267a72c16006", | |
| 73 | + "version" : "3.3.2" | |
| 74 | + } | |
| 75 | + } | |
| 76 | + ], | |
| 77 | + "version" : 3 | |
| 78 | +} | |
added
Package.swift
+47 −0
@@ -0,0 +1,47 @@ | ||
| 1 | +// swift-tools-version:5.10 | |
| 2 | +// | |
| 3 | +// Package.swift | |
| 4 | +// OS Vault | |
| 5 | +// | |
| 6 | +// Author: Simon-Pierre Boucher | |
| 7 | +// Mail: contact@spboucher.ai | |
| 8 | +// | |
| 9 | + | |
| 10 | +import PackageDescription | |
| 11 | + | |
| 12 | +let package = Package( | |
| 13 | + name: "OSVault", | |
| 14 | + platforms: [ | |
| 15 | + .macOS(.v14) | |
| 16 | + ], | |
| 17 | + dependencies: [ | |
| 18 | + .package(url: "https://github.com/web3swift-team/web3swift.git", from: "3.3.2"), | |
| 19 | + .package(url: "https://github.com/attaswift/BigInt.git", from: "5.3.0"), | |
| 20 | + .package(url: "https://github.com/bitcoindevkit/bdk-swift", exact: "3.0.0"), | |
| 21 | + .package(path: "vendor/solana-swift"), | |
| 22 | + .package(path: "vendor/WalletCoreSPM") | |
| 23 | + ], | |
| 24 | + targets: [ | |
| 25 | + .target( | |
| 26 | + name: "OSVaultKit", | |
| 27 | + dependencies: [ | |
| 28 | + .product(name: "web3swift", package: "web3swift"), | |
| 29 | + .product(name: "BigInt", package: "BigInt"), | |
| 30 | + .product(name: "BitcoinDevKit", package: "bdk-swift"), | |
| 31 | + .product(name: "SolanaSwift", package: "solana-swift"), | |
| 32 | + .product(name: "WalletCore", package: "WalletCoreSPM") | |
| 33 | + ], | |
| 34 | + path: "Sources/OSVaultKit" | |
| 35 | + ), | |
| 36 | + .executableTarget( | |
| 37 | + name: "OSVault", | |
| 38 | + dependencies: ["OSVaultKit"], | |
| 39 | + path: "Sources/OSVault" | |
| 40 | + ), | |
| 41 | + .testTarget( | |
| 42 | + name: "OSVaultTests", | |
| 43 | + dependencies: ["OSVaultKit"], | |
| 44 | + path: "Tests/OSVaultTests" | |
| 45 | + ) | |
| 46 | + ] | |
| 47 | +) | |
added
README.md
+154 −0
@@ -0,0 +1,154 @@ | ||
| 1 | +<div align="center"> | |
| 2 | + | |
| 3 | +<img src="assets/icon/os-vault.svg" width="128" alt="OS Vault icon"/> | |
| 4 | + | |
| 5 | +# OS Vault | |
| 6 | + | |
| 7 | +**Self-custody, multi-chain crypto wallet for macOS.** | |
| 8 | +One recovery phrase. Six chain families. Zero API keys. Nothing ever leaves your Mac. | |
| 9 | + | |
| 10 | +[](#requirements) | |
| 11 | +[](#build) | |
| 12 | +[](#architecture) | |
| 13 | +[](#tests) | |
| 14 | +[](../../releases) | |
| 15 | +[](#release-pipeline) | |
| 16 | +[](#infrastructure--no-api-keys) | |
| 17 | +[](#security-model) | |
| 18 | + | |
| 19 | +[](#chains) | |
| 20 | +[](#chains) | |
| 21 | +[](#chains) | |
| 22 | +[](#chains) | |
| 23 | +[](#chains) | |
| 24 | +[](#chains) | |
| 25 | + | |
| 26 | +</div> | |
| 27 | + | |
| 28 | +--- | |
| 29 | + | |
| 30 | +## Why OS Vault | |
| 31 | + | |
| 32 | +Most wallets make you choose: convenience (custodial, tracked, keyed APIs) or | |
| 33 | +sovereignty (CLI tools, manual everything). OS Vault refuses the trade: | |
| 34 | + | |
| 35 | +- 🔐 **Your keys, your Mac, your encryption.** The BIP-39 mnemonic is sealed | |
| 36 | + with OS Vault's **own vault format** — PBKDF2-HMAC-SHA512 (600k rounds) → | |
| 37 | + AES-256-GCM — in a local file. No macOS Keychain, no iCloud, no telemetry. | |
| 38 | +- 🌐 **One phrase, every chain.** The same 12 words derive Bitcoin (BIP-84), | |
| 39 | + 11 EVM chains, Solana, Tron, XRPL and TON — cross-validated against | |
| 40 | + independent crypto stacks in the test suite. | |
| 41 | +- 🗝️ **Zero mandatory API keys.** Every endpoint is public and keyless, with | |
| 42 | + automatic failover. The only egress is blockchain RPC (+ optional CoinGecko | |
| 43 | + prices, one toggle to kill). | |
| 44 | +- ✍️ **Sign-and-forget.** The private key exists only for the milliseconds a | |
| 45 | + transaction is being signed — every send re-derives it from your password | |
| 46 | + and discards it. | |
| 47 | + | |
| 48 | +## Chains | |
| 49 | + | |
| 50 | +| Family | Assets | Fees handled | Testnet default | | |
| 51 | +|---|---|---|---| | |
| 52 | +| **EVM × 11** — Ethereum, Base, Arbitrum, OP, Polygon, BNB, Avalanche, Gnosis, Linea, Scroll (+ Base Sepolia) | USDC, USDC.e, USDT, DAI, USDS, EURC + native coin | EIP-1559, BSC zero-base-fee, **OP-stack/Scroll L1 data fee via oracle**, Arbitrum inclusive estimates, Linea pinned base | Base Sepolia | | |
| 53 | +| **Bitcoin** | BTC (native SegWit `bc1q…`) | sat/vB presets live from mempool.space, RBF on | Signet | | |
| 54 | +| **Solana** | SOL + USDC (SPL) | ATA rent surfaced when the recipient has no token account | Devnet | | |
| 55 | +| **Tron** | TRX + USDT (TRC-20) | **Energy burn estimated pre-send** (~13–27 TRX), fee_limit capped | Nile | | |
| 56 | +| **XRP Ledger** | XRP + RLUSD | Reserves shown as locked; **one-tap RLUSD trustline**; recipient trustline checked | Testnet | | |
| 57 | +| **TON** | TON + USDT (jetton) | Jetton-wallet indirection handled; ~0.07 TON attached, excess refunded | Testnet | | |
| 58 | + | |
| 59 | +Every stablecoin contract address and decimal count was **verified live | |
| 60 | +on-chain** before registration — including the traps: BNB-peg USDT/USDC are | |
| 61 | +18 decimals, bridged USDC.e is indistinguishable from native USDC by | |
| 62 | +`symbol()` alone, DAI is 18 while USDC is 6. See | |
| 63 | +[`docs/STABLECOINS.md`](docs/STABLECOINS.md). | |
| 64 | + | |
| 65 | +## Security model | |
| 66 | + | |
| 67 | +``` | |
| 68 | +password ──▶ PBKDF2-HMAC-SHA512 (600k) ──▶ AES-256-GCM ──▶ vault.json (0600) | |
| 69 | + ▲ | |
| 70 | + wrong password / tampering ─┘ indistinguishable (GCM auth) | |
| 71 | + | |
| 72 | +unlock ──▶ public addresses only stay in memory | |
| 73 | +send ──▶ password → derive key → sign → discard (every single time) | |
| 74 | +``` | |
| 75 | + | |
| 76 | +- Forced written-backup verification (3 random words) before the wallet exists | |
| 77 | +- Confirm screen with recipient, amount, network, worst-case fees — always | |
| 78 | +- EIP-55 checksums; per-chain address validation; TESTNET badges everywhere | |
| 79 | +- App Sandbox + Hardened Runtime; signed, **notarized and stapled** by Apple | |
| 80 | +- The watch-only Bitcoin wallet holds public descriptors only; a throwaway | |
| 81 | + in-memory signer signs PSBTs | |
| 82 | + | |
| 83 | +## Infrastructure — no API keys | |
| 84 | + | |
| 85 | +| Concern | Source (keyless) | Fallback | | |
| 86 | +|---|---|---| | |
| 87 | +| EVM RPC | PublicNode (11/11 verified) | official chain RPCs, health-scored failover | | |
| 88 | +| Bitcoin | mempool.space Esplora | blockstream.info | | |
| 89 | +| Solana | PublicNode | api.mainnet-beta.solana.com | | |
| 90 | +| Tron | TronGrid (anonymous, backoff) | — | | |
| 91 | +| XRPL | xrplcluster.com | s1.ripple.com | | |
| 92 | +| TON | toncenter v2/v3 (1 req/s, throttled client-side) | — | | |
| 93 | +| Prices | CoinGecko batched (USD/CAD/EUR), stale-while-revalidate, **off switch** | DefiLlama | | |
| 94 | + | |
| 95 | +## Build | |
| 96 | + | |
| 97 | +Pure SwiftPM — no `.xcodeproj`, no CocoaPods, no manual steps: | |
| 98 | + | |
| 99 | +```sh | |
| 100 | +scripts/vendor-walletcore.sh # one-time: vendors Trust wallet-core for macOS (~270 MB, not in git) | |
| 101 | +swift build # compile | |
| 102 | +swift test # 32 tests: BIP-39/BIP-84 vectors, vault crypto, decimals, validators | |
| 103 | +make dev # debug bundle, ad-hoc signed, launched | |
| 104 | +make release # Developer ID + notarize + staple + DMG with volume icon | |
| 105 | +``` | |
| 106 | + | |
| 107 | +The wallet-core vendoring is this repo's party trick: upstream ships no macOS | |
| 108 | +SwiftPM support, so the script repackages the official CocoaPods tarball as a | |
| 109 | +local `binaryTarget` — including a surgical `ld -r` pass that demotes the | |
| 110 | +duplicate Rust runtime symbol it shares with the Bitcoin Dev Kit. Details in | |
| 111 | +[`docs/RESEARCH-MULTICHAIN.md`](docs/RESEARCH-MULTICHAIN.md). | |
| 112 | + | |
| 113 | +## Architecture | |
| 114 | + | |
| 115 | +``` | |
| 116 | +Sources/OSVaultKit | |
| 117 | +├── Services | |
| 118 | +│ ├── VaultCrypto ← the encryption mechanism (no Keychain) | |
| 119 | +│ ├── KeyManager ← BIP-39, HD derivation, vault lifecycle | |
| 120 | +│ ├── RPCService ← EVM JSON-RPC with endpoint failover | |
| 121 | +│ ├── TransactionService ← EIP-1559 + 5 other real fee models | |
| 122 | +│ ├── BitcoinService ← bdk-swift, watch-only + transient signer | |
| 123 | +│ ├── SolanaService ← solana-swift (vendored), SPL + ATA | |
| 124 | +│ ├── TronService ← wallet-core signing + TronGrid REST | |
| 125 | +│ ├── XRPLService ← wallet-core signing + xrplcluster JSON-RPC | |
| 126 | +│ ├── TONService ← wallet-core signing + toncenter v2/v3 | |
| 127 | +│ └── PriceService ← CoinGecko keyless, cached, optional | |
| 128 | +├── Models ← Network (chain registry), Token (verified matrix)… | |
| 129 | +└── Views ← SwiftUI: onboarding, home, per-chain panels | |
| 130 | +``` | |
| 131 | + | |
| 132 | +## Requirements | |
| 133 | + | |
| 134 | +- macOS 15.5+ (Apple silicon or Intel) | |
| 135 | +- That's it. No accounts, no keys, no configuration. | |
| 136 | + | |
| 137 | +## Testnet quickstart | |
| 138 | + | |
| 139 | +1. Create a wallet (write the 12 words down — the app makes you prove it). | |
| 140 | +2. Fund: [Circle faucet](https://faucet.circle.com) (USDC on Base Sepolia + | |
| 141 | + Solana devnet), a Base Sepolia ETH faucet, [mempool.space signet | |
| 142 | + faucet](https://signetfaucet.com), [nileex.io](https://nileex.io) (TRX + | |
| 143 | + test USDT), [XRPL faucet](https://xrpl.org/resources/dev-tools/xrp-faucets), | |
| 144 | + [@testgiver_ton_bot](https://t.me/testgiver_ton_bot). | |
| 145 | +3. Send. Watch it confirm on the linked explorer. | |
| 146 | + | |
| 147 | +--- | |
| 148 | + | |
| 149 | +<div align="center"> | |
| 150 | + | |
| 151 | +**Built with Swift, paranoia, and a refusal to type API keys.** | |
| 152 | +© 2026 Simon-Pierre Boucher · [contact@spboucher.ai](mailto:contact@spboucher.ai) | |
| 153 | + | |
| 154 | +</div> | |
added
Sources/OSVault/main.swift
+11 −0
@@ -0,0 +1,11 @@ | ||
| 1 | +// | |
| 2 | +// main.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import OSVaultKit | |
| 10 | + | |
| 11 | +OSVaultApp.main() | |
added
Sources/OSVaultKit/App/AppState.swift
+344 −0
@@ -0,0 +1,344 @@ | ||
| 1 | +// | |
| 2 | +// AppState.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import SwiftUI | |
| 11 | +import BigInt | |
| 12 | + | |
| 13 | +/// Single source of truth for the UI. Holds the public wallet address and | |
| 14 | +/// balances; never the private key — signing re-derives it from the vault | |
| 15 | +/// password at confirmation time and discards it immediately. | |
| 16 | +@MainActor | |
| 17 | +public final class AppState: ObservableObject { | |
| 18 | + | |
| 19 | + public enum Phase: Equatable { | |
| 20 | + case onboarding | |
| 21 | + case locked | |
| 22 | + case unlocked | |
| 23 | + } | |
| 24 | + | |
| 25 | + @Published public var phase: Phase | |
| 26 | + @Published public var address: String? | |
| 27 | + @Published public var network: Network { | |
| 28 | + didSet { | |
| 29 | + UserDefaults.standard.set(network.rawValue, forKey: Self.networkKey) | |
| 30 | + restartPollingIfUnlocked() | |
| 31 | + } | |
| 32 | + } | |
| 33 | + @Published public var balances = Balances() | |
| 34 | + @Published public var balancesLoaded = false | |
| 35 | + @Published public var balanceError: String? | |
| 36 | + @Published public var history: [TransactionRecord] = [] | |
| 37 | + @Published public var fiatPrices: [String: Decimal] = [:] | |
| 38 | + @Published public var pricesEnabled: Bool { | |
| 39 | + didSet { | |
| 40 | + UserDefaults.standard.set(pricesEnabled, forKey: PriceService.enabledKey) | |
| 41 | + if pricesEnabled { Task { await refreshPrices() } } else { fiatPrices = [:] } | |
| 42 | + } | |
| 43 | + } | |
| 44 | + @Published public var fiatCurrency: String { | |
| 45 | + didSet { | |
| 46 | + UserDefaults.standard.set(fiatCurrency, forKey: PriceService.fiatKey) | |
| 47 | + Task { await refreshPrices() } | |
| 48 | + } | |
| 49 | + } | |
| 50 | + | |
| 51 | + public let priceService = PriceService() | |
| 52 | + public let bitcoinService = BitcoinService() | |
| 53 | + public let solanaService = SolanaService() | |
| 54 | + public let tronService = TronService() | |
| 55 | + public let xrplService = XRPLService() | |
| 56 | + @Published public var xrplBalances: XRPLService.XRPLBalances? | |
| 57 | + @Published public var xrplAddress: String? | |
| 58 | + @Published public var xrplError: String? | |
| 59 | + @Published public var xrplNetwork: XRPLService.XRPLNetwork = .testnet | |
| 60 | + public let tonService = TONService() | |
| 61 | + @Published public var tonBalancesState: TONService.TONBalances? | |
| 62 | + @Published public var tonAddress: String? | |
| 63 | + @Published public var tonError: String? | |
| 64 | + @Published public var tonNetwork: TONService.TONNetwork = .testnet | |
| 65 | + @Published public var tronBalances: TronService.TronBalances? | |
| 66 | + @Published public var tronAddress: String? | |
| 67 | + @Published public var tronError: String? | |
| 68 | + @Published public var tronNetwork: TronService.TronNetwork = .nile | |
| 69 | + @Published public var solBalances: SolanaService.SOLBalances? | |
| 70 | + @Published public var solAddress: String? | |
| 71 | + @Published public var solError: String? | |
| 72 | + @Published public var solNetwork: SolanaService.SOLNetwork = .devnet | |
| 73 | + @Published public var btcBalance: BitcoinService.BTCBalance? | |
| 74 | + @Published public var btcSyncing = false | |
| 75 | + @Published public var btcError: String? | |
| 76 | + @Published public var btcNetwork: BitcoinService.BTCNetwork = .signet | |
| 77 | + public let keyManager: KeyManager | |
| 78 | + let historyStore: HistoryStore | |
| 79 | + private var pollTask: Task<Void, Never>? | |
| 80 | + | |
| 81 | + static let networkKey = "osvault.network" | |
| 82 | + public static let pollInterval: Duration = .seconds(15) | |
| 83 | + | |
| 84 | + public init(keyManager: KeyManager = KeyManager(), historyStore: HistoryStore = HistoryStore()) { | |
| 85 | + self.keyManager = keyManager | |
| 86 | + self.historyStore = historyStore | |
| 87 | + let saved = UserDefaults.standard.string(forKey: Self.networkKey) | |
| 88 | + self.network = saved.flatMap(Network.init(rawValue:)) ?? .baseSepolia | |
| 89 | + self.phase = keyManager.hasVault ? .locked : .onboarding | |
| 90 | + self.history = historyStore.load() | |
| 91 | + self.pricesEnabled = UserDefaults.standard.object(forKey: PriceService.enabledKey) as? Bool ?? true | |
| 92 | + self.fiatCurrency = UserDefaults.standard.string(forKey: PriceService.fiatKey) ?? "USD" | |
| 93 | + } | |
| 94 | + | |
| 95 | + public func rpc() -> RPCService { | |
| 96 | + RPCService(urls: network.rpcURLs) | |
| 97 | + } | |
| 98 | + | |
| 99 | + // MARK: - Session | |
| 100 | + | |
| 101 | + public func didUnlock(wallet: KeyManager.UnlockedWallet) { | |
| 102 | + self.address = wallet.address | |
| 103 | + self.phase = .unlocked | |
| 104 | + let mnemonic = wallet.mnemonic | |
| 105 | + Task { | |
| 106 | + do { | |
| 107 | + try await bitcoinService.configure(mnemonic: mnemonic) | |
| 108 | + btcNetwork = await bitcoinService.currentNetwork | |
| 109 | + await refreshBitcoin() | |
| 110 | + } catch { | |
| 111 | + btcError = error.localizedDescription | |
| 112 | + } | |
| 113 | + } | |
| 114 | + Task { | |
| 115 | + do { | |
| 116 | + try await solanaService.configure(mnemonic: mnemonic) | |
| 117 | + solNetwork = await solanaService.currentNetwork | |
| 118 | + solAddress = await solanaService.publicAddress | |
| 119 | + await refreshSolana() | |
| 120 | + } catch { | |
| 121 | + solError = error.localizedDescription | |
| 122 | + } | |
| 123 | + } | |
| 124 | + Task { | |
| 125 | + do { | |
| 126 | + try await tronService.configure(mnemonic: mnemonic) | |
| 127 | + tronNetwork = await tronService.currentNetwork | |
| 128 | + tronAddress = await tronService.publicAddress | |
| 129 | + await refreshTron() | |
| 130 | + } catch { | |
| 131 | + tronError = error.localizedDescription | |
| 132 | + } | |
| 133 | + } | |
| 134 | + Task { | |
| 135 | + do { | |
| 136 | + try await xrplService.configure(mnemonic: mnemonic) | |
| 137 | + xrplNetwork = await xrplService.currentNetwork | |
| 138 | + xrplAddress = await xrplService.publicAddress | |
| 139 | + await refreshXRPL() | |
| 140 | + } catch { | |
| 141 | + xrplError = error.localizedDescription | |
| 142 | + } | |
| 143 | + } | |
| 144 | + Task { | |
| 145 | + do { | |
| 146 | + try await tonService.configure(mnemonic: mnemonic) | |
| 147 | + tonNetwork = await tonService.currentNetwork | |
| 148 | + tonAddress = await tonService.publicAddress | |
| 149 | + await refreshTON() | |
| 150 | + } catch { | |
| 151 | + tonError = error.localizedDescription | |
| 152 | + } | |
| 153 | + } | |
| 154 | + startPolling() | |
| 155 | + } | |
| 156 | + | |
| 157 | + public func refreshBitcoin() async { | |
| 158 | + guard await bitcoinService.isConfigured else { return } | |
| 159 | + btcSyncing = true | |
| 160 | + defer { btcSyncing = false } | |
| 161 | + do { | |
| 162 | + try await bitcoinService.sync() | |
| 163 | + btcBalance = await bitcoinService.balance() | |
| 164 | + btcError = nil | |
| 165 | + } catch { | |
| 166 | + btcError = error.localizedDescription | |
| 167 | + } | |
| 168 | + } | |
| 169 | + | |
| 170 | + public func refreshSolana() async { | |
| 171 | + guard await solanaService.isConfigured else { return } | |
| 172 | + do { | |
| 173 | + solBalances = try await solanaService.fetchBalances() | |
| 174 | + solError = nil | |
| 175 | + } catch { | |
| 176 | + solError = error.localizedDescription | |
| 177 | + } | |
| 178 | + } | |
| 179 | + | |
| 180 | + public func refreshTron() async { | |
| 181 | + guard await tronService.isConfigured else { return } | |
| 182 | + do { | |
| 183 | + tronBalances = try await tronService.fetchBalances() | |
| 184 | + tronError = nil | |
| 185 | + } catch { | |
| 186 | + tronError = error.localizedDescription | |
| 187 | + } | |
| 188 | + } | |
| 189 | + | |
| 190 | + public func switchTronNetwork(to newNetwork: TronService.TronNetwork) async { | |
| 191 | + await tronService.switchNetwork(to: newNetwork) | |
| 192 | + tronNetwork = newNetwork | |
| 193 | + tronBalances = nil | |
| 194 | + await refreshTron() | |
| 195 | + } | |
| 196 | + | |
| 197 | + public func refreshXRPL() async { | |
| 198 | + guard await xrplService.isConfigured else { return } | |
| 199 | + do { | |
| 200 | + xrplBalances = try await xrplService.fetchBalances() | |
| 201 | + xrplError = nil | |
| 202 | + } catch { | |
| 203 | + xrplError = error.localizedDescription | |
| 204 | + } | |
| 205 | + } | |
| 206 | + | |
| 207 | + public func switchXRPLNetwork(to newNetwork: XRPLService.XRPLNetwork) async { | |
| 208 | + await xrplService.switchNetwork(to: newNetwork) | |
| 209 | + xrplNetwork = newNetwork | |
| 210 | + xrplBalances = nil | |
| 211 | + await refreshXRPL() | |
| 212 | + } | |
| 213 | + | |
| 214 | + public func refreshTON() async { | |
| 215 | + guard await tonService.isConfigured else { return } | |
| 216 | + do { | |
| 217 | + tonBalancesState = try await tonService.fetchBalances() | |
| 218 | + tonError = nil | |
| 219 | + } catch { | |
| 220 | + tonError = error.localizedDescription | |
| 221 | + } | |
| 222 | + } | |
| 223 | + | |
| 224 | + public func switchTONNetwork(to newNetwork: TONService.TONNetwork) async { | |
| 225 | + await tonService.switchNetwork(to: newNetwork) | |
| 226 | + tonNetwork = newNetwork | |
| 227 | + tonBalancesState = nil | |
| 228 | + await refreshTON() | |
| 229 | + } | |
| 230 | + | |
| 231 | + public func switchSolanaNetwork(to newNetwork: SolanaService.SOLNetwork) async { | |
| 232 | + await solanaService.switchNetwork(to: newNetwork) | |
| 233 | + solNetwork = newNetwork | |
| 234 | + solBalances = nil | |
| 235 | + await refreshSolana() | |
| 236 | + } | |
| 237 | + | |
| 238 | + /// Re-derives descriptors for the new BTC network; needs the password. | |
| 239 | + public func switchBitcoinNetwork(to newNetwork: BitcoinService.BTCNetwork, password: String) async throws { | |
| 240 | + let mnemonic = try await Task.detached { [keyManager] in | |
| 241 | + try keyManager.unlock(password: password).mnemonic | |
| 242 | + }.value | |
| 243 | + try await bitcoinService.switchNetwork(to: newNetwork, mnemonic: mnemonic) | |
| 244 | + btcNetwork = newNetwork | |
| 245 | + btcBalance = nil | |
| 246 | + await refreshBitcoin() | |
| 247 | + } | |
| 248 | + | |
| 249 | + public func lock() { | |
| 250 | + pollTask?.cancel() | |
| 251 | + pollTask = nil | |
| 252 | + address = nil | |
| 253 | + balances = Balances() | |
| 254 | + balancesLoaded = false | |
| 255 | + phase = .locked | |
| 256 | + } | |
| 257 | + | |
| 258 | + public func walletDeleted() { | |
| 259 | + pollTask?.cancel() | |
| 260 | + pollTask = nil | |
| 261 | + address = nil | |
| 262 | + balances = Balances() | |
| 263 | + balancesLoaded = false | |
| 264 | + history = [] | |
| 265 | + historyStore.clear() | |
| 266 | + btcBalance = nil | |
| 267 | + solBalances = nil | |
| 268 | + solAddress = nil | |
| 269 | + tronBalances = nil | |
| 270 | + tronAddress = nil | |
| 271 | + xrplBalances = nil | |
| 272 | + xrplAddress = nil | |
| 273 | + tonBalancesState = nil | |
| 274 | + tonAddress = nil | |
| 275 | + // Remove the BDK watch-only databases and scan flags with the vault. | |
| 276 | + let support = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] | |
| 277 | + for network in BitcoinService.BTCNetwork.allCases { | |
| 278 | + try? FileManager.default.removeItem( | |
| 279 | + at: support.appendingPathComponent("OSVault/bdk-\(network.rawValue).sqlite")) | |
| 280 | + UserDefaults.standard.removeObject(forKey: "osvault.bitcoin.scanned.\(network.rawValue)") | |
| 281 | + } | |
| 282 | + phase = .onboarding | |
| 283 | + } | |
| 284 | + | |
| 285 | + // MARK: - Balances | |
| 286 | + | |
| 287 | + public func refreshBalances() async { | |
| 288 | + guard let address else { return } | |
| 289 | + do { | |
| 290 | + let fetched = try await BalanceService.fetch(address: address, network: network, rpc: rpc()) | |
| 291 | + balances = fetched | |
| 292 | + balancesLoaded = true | |
| 293 | + balanceError = nil | |
| 294 | + } catch { | |
| 295 | + balanceError = error.localizedDescription | |
| 296 | + } | |
| 297 | + } | |
| 298 | + | |
| 299 | + public func refreshPrices() async { | |
| 300 | + guard pricesEnabled else { return } | |
| 301 | + let symbols = Token.available(on: network).map(\.symbol) | |
| 302 | + + [network.config.nativeSymbol, "BTC", "SOL", "TRX", "USDT", "XRP", "TON"] | |
| 303 | + fiatPrices = await priceService.prices(for: symbols, fiat: fiatCurrency) | |
| 304 | + } | |
| 305 | + | |
| 306 | + private func startPolling() { | |
| 307 | + pollTask?.cancel() | |
| 308 | + pollTask = Task { [weak self] in | |
| 309 | + var tick = 0 | |
| 310 | + while !Task.isCancelled { | |
| 311 | + await self?.refreshBalances() | |
| 312 | + await self?.refreshPrices() | |
| 313 | + // Bitcoin blocks are ~10 min; sync every 4th tick (60 s). | |
| 314 | + if tick % 4 == 0 { await self?.refreshBitcoin() } | |
| 315 | + if tick % 2 == 0 { await self?.refreshSolana() } | |
| 316 | + if tick % 2 == 1 { await self?.refreshTron() } | |
| 317 | + if tick % 4 == 1 { await self?.refreshXRPL() } | |
| 318 | + if tick % 4 == 3 { await self?.refreshTON() } | |
| 319 | + tick += 1 | |
| 320 | + try? await Task.sleep(for: Self.pollInterval) | |
| 321 | + } | |
| 322 | + } | |
| 323 | + } | |
| 324 | + | |
| 325 | + private func restartPollingIfUnlocked() { | |
| 326 | + guard phase == .unlocked else { return } | |
| 327 | + balances = Balances() | |
| 328 | + balancesLoaded = false | |
| 329 | + startPolling() | |
| 330 | + } | |
| 331 | + | |
| 332 | + // MARK: - History | |
| 333 | + | |
| 334 | + public func recordSend(_ record: TransactionRecord) { | |
| 335 | + history.insert(record, at: 0) | |
| 336 | + historyStore.save(history) | |
| 337 | + } | |
| 338 | + | |
| 339 | + public func updateRecord(hash: String, status: TransactionRecord.Status) { | |
| 340 | + guard let index = history.firstIndex(where: { $0.hash == hash }) else { return } | |
| 341 | + history[index].status = status | |
| 342 | + historyStore.save(history) | |
| 343 | + } | |
| 344 | +} | |
added
Sources/OSVaultKit/App/OSVaultApp.swift
+39 −0
@@ -0,0 +1,39 @@ | ||
| 1 | +// | |
| 2 | +// OSVaultApp.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | + | |
| 11 | +public struct OSVaultApp: App { | |
| 12 | + @StateObject private var app = AppState() | |
| 13 | + | |
| 14 | + public init() {} | |
| 15 | + | |
| 16 | + public var body: some Scene { | |
| 17 | + WindowGroup { | |
| 18 | + ContentView() | |
| 19 | + .environmentObject(app) | |
| 20 | + .frame(minWidth: 520, minHeight: 640) | |
| 21 | + } | |
| 22 | + .windowResizability(.contentSize) | |
| 23 | + } | |
| 24 | +} | |
| 25 | + | |
| 26 | +struct ContentView: View { | |
| 27 | + @EnvironmentObject var app: AppState | |
| 28 | + | |
| 29 | + var body: some View { | |
| 30 | + switch app.phase { | |
| 31 | + case .onboarding: | |
| 32 | + OnboardingView() | |
| 33 | + case .locked: | |
| 34 | + UnlockView() | |
| 35 | + case .unlocked: | |
| 36 | + HomeView() | |
| 37 | + } | |
| 38 | + } | |
| 39 | +} | |
added
Sources/OSVaultKit/Models/Asset.swift
+51 −0
@@ -0,0 +1,51 @@ | ||
| 1 | +// | |
| 2 | +// Asset.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | + | |
| 11 | +/// Anything the wallet can send on an EVM chain: the chain's native coin | |
| 12 | +/// (ETH, POL, BNB, AVAX, xDAI… — also the gas currency) or a registered | |
| 13 | +/// ERC-20 stablecoin. Native symbol/name depend on the chain, so they are | |
| 14 | +/// resolved against a Network. | |
| 15 | +public enum Asset: Identifiable, Hashable, Sendable { | |
| 16 | + case native | |
| 17 | + case token(Token) | |
| 18 | + | |
| 19 | + public var id: String { | |
| 20 | + switch self { | |
| 21 | + case .native: return "native" | |
| 22 | + case .token(let token): return "token-\(token.symbol)" | |
| 23 | + } | |
| 24 | + } | |
| 25 | + | |
| 26 | + public func symbol(on network: Network) -> String { | |
| 27 | + switch self { | |
| 28 | + case .native: return network.config.nativeSymbol | |
| 29 | + case .token(let token): return token.symbol | |
| 30 | + } | |
| 31 | + } | |
| 32 | + | |
| 33 | + public func name(on network: Network) -> String { | |
| 34 | + switch self { | |
| 35 | + case .native: return network.config.nativeName | |
| 36 | + case .token(let token): return token.name | |
| 37 | + } | |
| 38 | + } | |
| 39 | + | |
| 40 | + /// All supported natives are 18 decimals (ETH, POL, BNB, AVAX, xDAI). | |
| 41 | + public var decimals: Int { | |
| 42 | + switch self { | |
| 43 | + case .native: return 18 | |
| 44 | + case .token(let token): return token.decimals | |
| 45 | + } | |
| 46 | + } | |
| 47 | + | |
| 48 | + public static func available(on network: Network) -> [Asset] { | |
| 49 | + Token.available(on: network).map(Asset.token) + [.native] | |
| 50 | + } | |
| 51 | +} | |
added
Sources/OSVaultKit/Models/Network.swift
+195 −0
@@ -0,0 +1,195 @@ | ||
| 1 | +// | |
| 2 | +// Network.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// The EVM chains OS Vault can talk to. Fully data-driven: adding a chain is | |
| 13 | +/// a new case + ChainConfig entry. Every chain id and RPC below was verified | |
| 14 | +/// live before being listed (see docs/RESEARCH-MULTICHAIN.md). Non-EVM chains | |
| 15 | +/// (Bitcoin, Solana, Tron, TON, XRPL…) use their own adapters. | |
| 16 | +public enum Network: String, CaseIterable, Codable, Identifiable, Sendable { | |
| 17 | + case baseSepolia // testnet — safe default for development | |
| 18 | + case baseMainnet | |
| 19 | + case ethereum | |
| 20 | + case arbitrum | |
| 21 | + case optimism | |
| 22 | + case polygon | |
| 23 | + case bnb | |
| 24 | + case avalanche | |
| 25 | + case gnosis | |
| 26 | + case linea | |
| 27 | + case scroll | |
| 28 | + | |
| 29 | + public var id: String { rawValue } | |
| 30 | + | |
| 31 | + /// How transaction fees actually work on this chain — the research | |
| 32 | + /// finding is that "EIP-1559" hides four distinct realities. | |
| 33 | + public enum FeeModel: Sendable { | |
| 34 | + /// Standard: maxFee = 2×baseFee + tip. | |
| 35 | + case eip1559 | |
| 36 | + /// BNB Chain (BEP-226): baseFee is 0; price via eth_gasPrice. | |
| 37 | + case zeroBaseFee | |
| 38 | + /// OP-stack (Base, Optimism): L2 fee + L1 data fee from the | |
| 39 | + /// GasPriceOracle predeploy at 0x42…0F, deducted silently. | |
| 40 | + case opStackL1Fee | |
| 41 | + /// Scroll: same idea, oracle at 0x5300…0002. | |
| 42 | + case scrollL1Fee | |
| 43 | + /// Arbitrum: estimateGas already folds the L1 buffer into gasLimit; | |
| 44 | + /// suggested tip is 0. | |
| 45 | + case arbitrumInclusive | |
| 46 | + /// Linea: base fee pinned at 7 wei; real cost rides in the tip. | |
| 47 | + case lineaPinnedBase | |
| 48 | + } | |
| 49 | + | |
| 50 | + public struct ChainConfig: Sendable { | |
| 51 | + public let chainID: BigUInt | |
| 52 | + public let displayName: String | |
| 53 | + public let nativeSymbol: String | |
| 54 | + public let nativeName: String | |
| 55 | + /// Ordered keyless endpoints: primary first, chain id verified live. | |
| 56 | + public let rpcs: [URL] | |
| 57 | + public let explorerBase: URL | |
| 58 | + public let feeModel: FeeModel | |
| 59 | + public let isTestnet: Bool | |
| 60 | + } | |
| 61 | + | |
| 62 | + public var config: ChainConfig { | |
| 63 | + switch self { | |
| 64 | + case .baseSepolia: | |
| 65 | + return ChainConfig( | |
| 66 | + chainID: 84532, displayName: "Base Sepolia", | |
| 67 | + nativeSymbol: "ETH", nativeName: "Ether", | |
| 68 | + rpcs: [URL(string: "https://sepolia.base.org")!, | |
| 69 | + URL(string: "https://base-sepolia-rpc.publicnode.com")!], | |
| 70 | + explorerBase: URL(string: "https://sepolia.basescan.org")!, | |
| 71 | + feeModel: .opStackL1Fee, isTestnet: true | |
| 72 | + ) | |
| 73 | + case .baseMainnet: | |
| 74 | + return ChainConfig( | |
| 75 | + chainID: 8453, displayName: "Base", | |
| 76 | + nativeSymbol: "ETH", nativeName: "Ether", | |
| 77 | + rpcs: [URL(string: "https://base-rpc.publicnode.com")!, | |
| 78 | + URL(string: "https://mainnet.base.org")!], | |
| 79 | + explorerBase: URL(string: "https://basescan.org")!, | |
| 80 | + feeModel: .opStackL1Fee, isTestnet: false | |
| 81 | + ) | |
| 82 | + case .ethereum: | |
| 83 | + return ChainConfig( | |
| 84 | + chainID: 1, displayName: "Ethereum", | |
| 85 | + nativeSymbol: "ETH", nativeName: "Ether", | |
| 86 | + rpcs: [URL(string: "https://ethereum-rpc.publicnode.com")!, | |
| 87 | + URL(string: "https://cloudflare-eth.com")!, | |
| 88 | + URL(string: "https://eth.merkle.io")!], | |
| 89 | + explorerBase: URL(string: "https://etherscan.io")!, | |
| 90 | + feeModel: .eip1559, isTestnet: false | |
| 91 | + ) | |
| 92 | + case .arbitrum: | |
| 93 | + return ChainConfig( | |
| 94 | + chainID: 42161, displayName: "Arbitrum One", | |
| 95 | + nativeSymbol: "ETH", nativeName: "Ether", | |
| 96 | + rpcs: [URL(string: "https://arbitrum-one-rpc.publicnode.com")!, | |
| 97 | + URL(string: "https://arb1.arbitrum.io/rpc")!], | |
| 98 | + explorerBase: URL(string: "https://arbiscan.io")!, | |
| 99 | + feeModel: .arbitrumInclusive, isTestnet: false | |
| 100 | + ) | |
| 101 | + case .optimism: | |
| 102 | + return ChainConfig( | |
| 103 | + chainID: 10, displayName: "OP Mainnet", | |
| 104 | + nativeSymbol: "ETH", nativeName: "Ether", | |
| 105 | + rpcs: [URL(string: "https://optimism-rpc.publicnode.com")!, | |
| 106 | + URL(string: "https://mainnet.optimism.io")!], | |
| 107 | + explorerBase: URL(string: "https://optimistic.etherscan.io")!, | |
| 108 | + feeModel: .opStackL1Fee, isTestnet: false | |
| 109 | + ) | |
| 110 | + case .polygon: | |
| 111 | + return ChainConfig( | |
| 112 | + chainID: 137, displayName: "Polygon", | |
| 113 | + nativeSymbol: "POL", nativeName: "Polygon Ecosystem Token", | |
| 114 | + rpcs: [URL(string: "https://polygon-bor-rpc.publicnode.com")!, | |
| 115 | + URL(string: "https://polygon.drpc.org")!], | |
| 116 | + explorerBase: URL(string: "https://polygonscan.com")!, | |
| 117 | + feeModel: .eip1559, isTestnet: false | |
| 118 | + ) | |
| 119 | + case .bnb: | |
| 120 | + return ChainConfig( | |
| 121 | + chainID: 56, displayName: "BNB Chain", | |
| 122 | + nativeSymbol: "BNB", nativeName: "BNB", | |
| 123 | + rpcs: [URL(string: "https://bsc-rpc.publicnode.com")!, | |
| 124 | + URL(string: "https://bsc-dataseed.bnbchain.org")!], | |
| 125 | + explorerBase: URL(string: "https://bscscan.com")!, | |
| 126 | + feeModel: .zeroBaseFee, isTestnet: false | |
| 127 | + ) | |
| 128 | + case .avalanche: | |
| 129 | + return ChainConfig( | |
| 130 | + chainID: 43114, displayName: "Avalanche C-Chain", | |
| 131 | + nativeSymbol: "AVAX", nativeName: "Avalanche", | |
| 132 | + rpcs: [URL(string: "https://avalanche-c-chain-rpc.publicnode.com")!, | |
| 133 | + URL(string: "https://api.avax.network/ext/bc/C/rpc")!], | |
| 134 | + explorerBase: URL(string: "https://snowtrace.io")!, | |
| 135 | + feeModel: .eip1559, isTestnet: false | |
| 136 | + ) | |
| 137 | + case .gnosis: | |
| 138 | + return ChainConfig( | |
| 139 | + chainID: 100, displayName: "Gnosis", | |
| 140 | + nativeSymbol: "xDAI", nativeName: "xDAI (dollar-pegged)", | |
| 141 | + rpcs: [URL(string: "https://gnosis-rpc.publicnode.com")!, | |
| 142 | + URL(string: "https://rpc.gnosischain.com")!], | |
| 143 | + explorerBase: URL(string: "https://gnosisscan.io")!, | |
| 144 | + feeModel: .eip1559, isTestnet: false | |
| 145 | + ) | |
| 146 | + case .linea: | |
| 147 | + return ChainConfig( | |
| 148 | + chainID: 59144, displayName: "Linea", | |
| 149 | + nativeSymbol: "ETH", nativeName: "Ether", | |
| 150 | + rpcs: [URL(string: "https://linea-rpc.publicnode.com")!, | |
| 151 | + URL(string: "https://rpc.linea.build")!], | |
| 152 | + explorerBase: URL(string: "https://lineascan.build")!, | |
| 153 | + feeModel: .lineaPinnedBase, isTestnet: false | |
| 154 | + ) | |
| 155 | + case .scroll: | |
| 156 | + return ChainConfig( | |
| 157 | + chainID: 534352, displayName: "Scroll", | |
| 158 | + nativeSymbol: "ETH", nativeName: "Ether", | |
| 159 | + rpcs: [URL(string: "https://scroll-rpc.publicnode.com")!, | |
| 160 | + URL(string: "https://rpc.scroll.io")!], | |
| 161 | + explorerBase: URL(string: "https://scrollscan.com")!, | |
| 162 | + feeModel: .scrollL1Fee, isTestnet: false | |
| 163 | + ) | |
| 164 | + } | |
| 165 | + } | |
| 166 | + | |
| 167 | + /// L1 data-fee oracle for rollups that charge one (`getL1Fee(bytes)`). | |
| 168 | + public var l1FeeOracle: String? { | |
| 169 | + switch config.feeModel { | |
| 170 | + case .opStackL1Fee: return "0x420000000000000000000000000000000000000F" | |
| 171 | + case .scrollL1Fee: return "0x5300000000000000000000000000000000000002" | |
| 172 | + default: return nil | |
| 173 | + } | |
| 174 | + } | |
| 175 | + | |
| 176 | + /// Active RPC endpoints, user override (Settings) first. | |
| 177 | + public var rpcURLs: [URL] { | |
| 178 | + var urls = config.rpcs | |
| 179 | + if let raw = UserDefaults.standard.string(forKey: rpcOverrideKey), | |
| 180 | + !raw.isEmpty, let url = URL(string: raw), url.scheme?.hasPrefix("http") == true { | |
| 181 | + urls.insert(url, at: 0) | |
| 182 | + } | |
| 183 | + return urls | |
| 184 | + } | |
| 185 | + | |
| 186 | + public var rpcOverrideKey: String { "osvault.rpcOverride.\(rawValue)" } | |
| 187 | + | |
| 188 | + public func explorerTxURL(_ hash: String) -> URL { | |
| 189 | + config.explorerBase.appendingPathComponent("tx/\(hash)") | |
| 190 | + } | |
| 191 | + | |
| 192 | + public func explorerAddressURL(_ address: String) -> URL { | |
| 193 | + config.explorerBase.appendingPathComponent("address/\(address)") | |
| 194 | + } | |
| 195 | +} | |
added
Sources/OSVaultKit/Models/Token.swift
+128 −0
@@ -0,0 +1,128 @@ | ||
| 1 | +// | |
| 2 | +// Token.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | + | |
| 11 | +/// An ERC-20 stablecoin deployment set. Every address and decimal count below | |
| 12 | +/// was verified live on-chain via `symbol()`/`decimals()` eth_calls | |
| 13 | +/// (docs/STABLECOINS.md + docs/RESEARCH-MULTICHAIN.md, 2026-08-05). | |
| 14 | +/// | |
| 15 | +/// Registry rules learned from that research: | |
| 16 | +/// - decimals are per-DEPLOYMENT data: USDT/USDC are 18 on BNB Chain, 6 | |
| 17 | +/// everywhere else — hence the separate BNB-peg entries. | |
| 18 | +/// - bridged USDC.e reports the same `symbol()` as native USDC on | |
| 19 | +/// Arbitrum/Optimism/Polygon; the registry distinguishes them by address | |
| 20 | +/// and shows "USDC.e" to the user. | |
| 21 | +/// - Arbitrum/Polygon USDT was upgraded in place to USDT0 (same address, | |
| 22 | +/// same 6 decimals) — never assert on-chain symbol strings. | |
| 23 | +public struct Token: Identifiable, Hashable, Sendable { | |
| 24 | + public let symbol: String | |
| 25 | + public let name: String | |
| 26 | + public let decimals: Int | |
| 27 | + /// Checksummed contract address per network the token is deployed on. | |
| 28 | + public let addresses: [Network: String] | |
| 29 | + | |
| 30 | + public var id: String { symbol } | |
| 31 | + | |
| 32 | + public func address(on network: Network) -> String? { | |
| 33 | + addresses[network] | |
| 34 | + } | |
| 35 | + | |
| 36 | + // MARK: - Registry | |
| 37 | + | |
| 38 | + public static let usdc = Token( | |
| 39 | + symbol: "USDC", name: "USD Coin", decimals: 6, | |
| 40 | + addresses: [ | |
| 41 | + .baseSepolia: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", | |
| 42 | + .baseMainnet: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", | |
| 43 | + .ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", | |
| 44 | + .arbitrum: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", | |
| 45 | + .optimism: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", | |
| 46 | + .polygon: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", | |
| 47 | + .avalanche: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", | |
| 48 | + .linea: "0x176211869cA2b568f2A7D4EE941E073a821EE1ff" | |
| 49 | + ] | |
| 50 | + ) | |
| 51 | + | |
| 52 | + /// Bridged USDC — same on-chain symbol as native USDC, different address. | |
| 53 | + public static let usdce = Token( | |
| 54 | + symbol: "USDC.e", name: "Bridged USDC", decimals: 6, | |
| 55 | + addresses: [ | |
| 56 | + .arbitrum: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", | |
| 57 | + .optimism: "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", | |
| 58 | + .polygon: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", | |
| 59 | + .avalanche: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664", | |
| 60 | + .gnosis: "0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0", | |
| 61 | + .scroll: "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4" | |
| 62 | + ] | |
| 63 | + ) | |
| 64 | + | |
| 65 | + public static let usdt = Token( | |
| 66 | + symbol: "USDT", name: "Tether USD", decimals: 6, | |
| 67 | + addresses: [ | |
| 68 | + .baseMainnet: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2", | |
| 69 | + .ethereum: "0xdAC17F958D2ee523a2206206994597C13D831ec7", | |
| 70 | + .arbitrum: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", // USDT0 in-place upgrade | |
| 71 | + .optimism: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58", | |
| 72 | + .polygon: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", // USDT0 in-place upgrade | |
| 73 | + .avalanche: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7", // native USDt | |
| 74 | + .gnosis: "0x4ECaBa5870353805a9F068101A40E0f32ed605C6", | |
| 75 | + .linea: "0xA219439258ca9da29E9Cc4cE5596924745e12B93", | |
| 76 | + .scroll: "0xf55BEC9cafDbE8730f096Aa55dad6D22d44099Df" | |
| 77 | + ] | |
| 78 | + ) | |
| 79 | + | |
| 80 | + /// Binance-peg variants: 18 decimals, not issuer-native. Kept as separate | |
| 81 | + /// registry entries because decimals differ from every other deployment. | |
| 82 | + public static let usdtBNB = Token( | |
| 83 | + symbol: "USDT", name: "Tether USD (BNB peg)", decimals: 18, | |
| 84 | + addresses: [.bnb: "0x55d398326f99059fF775485246999027B3197955"] | |
| 85 | + ) | |
| 86 | + | |
| 87 | + public static let usdcBNB = Token( | |
| 88 | + symbol: "USDC", name: "USD Coin (BNB peg)", decimals: 18, | |
| 89 | + addresses: [.bnb: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"] | |
| 90 | + ) | |
| 91 | + | |
| 92 | + public static let dai = Token( | |
| 93 | + symbol: "DAI", name: "Dai Stablecoin", decimals: 18, | |
| 94 | + addresses: [ | |
| 95 | + .baseMainnet: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", | |
| 96 | + .ethereum: "0x6B175474E89094C44Da98b954EedeAC495271d0F", | |
| 97 | + .arbitrum: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", | |
| 98 | + .optimism: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", | |
| 99 | + .polygon: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", | |
| 100 | + .bnb: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3", | |
| 101 | + .avalanche: "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70", // DAI.e | |
| 102 | + .linea: "0x4AF15ec2A0BD43Db75dd04E62FAA3B8EF36b00d5", | |
| 103 | + .scroll: "0xcA77eB3fEFe3725Dc33bccB54eDEFc3D9f764f97" | |
| 104 | + ] | |
| 105 | + ) | |
| 106 | + | |
| 107 | + public static let usds = Token( | |
| 108 | + symbol: "USDS", name: "Sky Dollar", decimals: 18, | |
| 109 | + addresses: [ | |
| 110 | + .ethereum: "0xdC035D45d973E3EC169d2276DDab16f1e407384F", | |
| 111 | + .baseMainnet: "0x820C137fa70C8691f0e44Dc420a5e53c168921Dc" | |
| 112 | + ] | |
| 113 | + ) | |
| 114 | + | |
| 115 | + public static let eurc = Token( | |
| 116 | + symbol: "EURC", name: "Euro Coin", decimals: 6, | |
| 117 | + addresses: [ | |
| 118 | + .baseMainnet: "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42" | |
| 119 | + ] | |
| 120 | + ) | |
| 121 | + | |
| 122 | + public static let all: [Token] = [usdc, usdcBNB, usdce, usdt, usdtBNB, dai, usds, eurc] | |
| 123 | + | |
| 124 | + /// Tokens usable on a given network, USDC-family first. | |
| 125 | + public static func available(on network: Network) -> [Token] { | |
| 126 | + all.filter { $0.addresses[network] != nil } | |
| 127 | + } | |
| 128 | +} | |
added
Sources/OSVaultKit/Models/TokenAmount.swift
+59 −0
@@ -0,0 +1,59 @@ | ||
| 1 | +// | |
| 2 | +// TokenAmount.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Integer-only conversion between base units and display strings. | |
| 13 | +/// `Double` is banned for money: 6- and 18-decimal tokens both exceed the | |
| 14 | +/// 53-bit mantissa long before real-world balances do. | |
| 15 | +public enum TokenAmount { | |
| 16 | + | |
| 17 | + /// "12.5" with decimals 6 → 12_500_000. Returns nil on malformed input or | |
| 18 | + /// more fraction digits than the token supports. Accepts "," as separator. | |
| 19 | + public static func parse(_ input: String, decimals: Int) -> BigUInt? { | |
| 20 | + let normalized = input | |
| 21 | + .trimmingCharacters(in: .whitespacesAndNewlines) | |
| 22 | + .replacingOccurrences(of: ",", with: ".") | |
| 23 | + guard !normalized.isEmpty, normalized != "." else { return nil } | |
| 24 | + | |
| 25 | + let parts = normalized.split(separator: ".", omittingEmptySubsequences: false) | |
| 26 | + guard parts.count <= 2 else { return nil } | |
| 27 | + | |
| 28 | + let wholePart = String(parts[0]) | |
| 29 | + let fracPart = parts.count == 2 ? String(parts[1]) : "" | |
| 30 | + guard wholePart.allSatisfy(\.isNumber), fracPart.allSatisfy(\.isNumber) else { return nil } | |
| 31 | + guard !(wholePart.isEmpty && fracPart.isEmpty) else { return nil } | |
| 32 | + guard fracPart.count <= decimals else { return nil } | |
| 33 | + | |
| 34 | + let whole = BigUInt(wholePart.isEmpty ? "0" : wholePart, radix: 10) ?? 0 | |
| 35 | + let paddedFrac = fracPart.padding(toLength: decimals, withPad: "0", startingAt: 0) | |
| 36 | + let frac = paddedFrac.isEmpty ? BigUInt(0) : (BigUInt(paddedFrac, radix: 10) ?? 0) | |
| 37 | + return whole * BigUInt(10).power(decimals) + frac | |
| 38 | + } | |
| 39 | + | |
| 40 | + /// 12_500_000 with decimals 6 → "12.5". Trailing zeros trimmed, | |
| 41 | + /// optionally capped to `maxFractionDigits` (truncated, never rounded up — | |
| 42 | + /// a wallet must not display more than the user owns). | |
| 43 | + public static func format(_ units: BigUInt, decimals: Int, maxFractionDigits: Int? = nil) -> String { | |
| 44 | + let divisor = BigUInt(10).power(decimals) | |
| 45 | + let whole = units / divisor | |
| 46 | + var frac = String(units % divisor) | |
| 47 | + frac = String(repeating: "0", count: max(0, decimals - frac.count)) + frac | |
| 48 | + if let cap = maxFractionDigits, frac.count > cap { | |
| 49 | + frac = String(frac.prefix(cap)) | |
| 50 | + } | |
| 51 | + while frac.hasSuffix("0") { frac.removeLast() } | |
| 52 | + return frac.isEmpty ? String(whole) : "\(whole).\(frac)" | |
| 53 | + } | |
| 54 | + | |
| 55 | + /// Wei → ETH display string (18 decimals), for gas costs. | |
| 56 | + public static func formatWei(_ wei: BigUInt, maxFractionDigits: Int = 8) -> String { | |
| 57 | + format(wei, decimals: 18, maxFractionDigits: maxFractionDigits) | |
| 58 | + } | |
| 59 | +} | |
added
Sources/OSVaultKit/Models/TransactionRecord.swift
+85 −0
@@ -0,0 +1,85 @@ | ||
| 1 | +// | |
| 2 | +// TransactionRecord.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// A send initiated from this app, persisted locally (non-sensitive data | |
| 13 | +/// only: it is all public on-chain anyway). Full history lives on the | |
| 14 | +/// explorer; each record links there. | |
| 15 | +public struct TransactionRecord: Identifiable, Codable, Equatable { | |
| 16 | + public enum Status: String, Codable { | |
| 17 | + case pending, confirmed, failed | |
| 18 | + } | |
| 19 | + | |
| 20 | + public let id: UUID | |
| 21 | + public let hash: String | |
| 22 | + public let tokenSymbol: String | |
| 23 | + public let tokenDecimals: Int | |
| 24 | + public let amountUnits: String // BigUInt as decimal string (Codable-safe) | |
| 25 | + public let recipient: String | |
| 26 | + public let network: Network | |
| 27 | + public var status: Status | |
| 28 | + public let date: Date | |
| 29 | + | |
| 30 | + public init(hash: String, asset: Asset, amountUnits: BigUInt, | |
| 31 | + recipient: String, network: Network, status: Status, date: Date = Date()) { | |
| 32 | + self.id = UUID() | |
| 33 | + self.hash = hash | |
| 34 | + self.tokenSymbol = asset.symbol(on: network) | |
| 35 | + self.tokenDecimals = asset.decimals | |
| 36 | + self.amountUnits = String(amountUnits) | |
| 37 | + self.recipient = recipient | |
| 38 | + self.network = network | |
| 39 | + self.status = status | |
| 40 | + self.date = date | |
| 41 | + } | |
| 42 | + | |
| 43 | + public var displayAmount: String { | |
| 44 | + guard let units = BigUInt(amountUnits, radix: 10) else { return amountUnits } | |
| 45 | + return TokenAmount.format(units, decimals: tokenDecimals) | |
| 46 | + } | |
| 47 | + | |
| 48 | + public var explorerURL: URL { network.explorerTxURL(hash) } | |
| 49 | +} | |
| 50 | + | |
| 51 | +/// JSON-file persistence for local send history. | |
| 52 | +public final class HistoryStore { | |
| 53 | + private let fileURL: URL | |
| 54 | + private let maxEntries = 200 | |
| 55 | + | |
| 56 | + public init(fileURL: URL? = nil) { | |
| 57 | + if let fileURL { | |
| 58 | + self.fileURL = fileURL | |
| 59 | + } else { | |
| 60 | + let support = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] | |
| 61 | + self.fileURL = support.appendingPathComponent("OSVault/history.json") | |
| 62 | + } | |
| 63 | + } | |
| 64 | + | |
| 65 | + public func load() -> [TransactionRecord] { | |
| 66 | + guard let data = try? Data(contentsOf: fileURL), | |
| 67 | + let records = try? JSONDecoder().decode([TransactionRecord].self, from: data) else { | |
| 68 | + return [] | |
| 69 | + } | |
| 70 | + return records | |
| 71 | + } | |
| 72 | + | |
| 73 | + public func save(_ records: [TransactionRecord]) { | |
| 74 | + let trimmed = Array(records.prefix(maxEntries)) | |
| 75 | + let dir = fileURL.deletingLastPathComponent() | |
| 76 | + try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) | |
| 77 | + if let data = try? JSONEncoder().encode(trimmed) { | |
| 78 | + try? data.write(to: fileURL, options: [.atomic]) | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | + public func clear() { | |
| 83 | + try? FileManager.default.removeItem(at: fileURL) | |
| 84 | + } | |
| 85 | +} | |
added
Sources/OSVaultKit/Models/WalletError.swift
+48 −0
@@ -0,0 +1,48 @@ | ||
| 1 | +// | |
| 2 | +// WalletError.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | + | |
| 11 | +/// Typed errors for every service call. Messages never contain key material. | |
| 12 | +public enum WalletError: LocalizedError, Equatable { | |
| 13 | + case noVault | |
| 14 | + case vaultCorrupted | |
| 15 | + case wrongPassword | |
| 16 | + case invalidMnemonic | |
| 17 | + case invalidAddress | |
| 18 | + case insufficientETHForGas(needWei: String, haveWei: String) | |
| 19 | + case insufficientTokenBalance | |
| 20 | + case rpc(String) | |
| 21 | + case signingFailed | |
| 22 | + case internalError(String) | |
| 23 | + | |
| 24 | + public var errorDescription: String? { | |
| 25 | + switch self { | |
| 26 | + case .noVault: | |
| 27 | + return "No wallet exists on this Mac yet." | |
| 28 | + case .vaultCorrupted: | |
| 29 | + return "The vault file is damaged and cannot be read." | |
| 30 | + case .wrongPassword: | |
| 31 | + return "Incorrect password." | |
| 32 | + case .invalidMnemonic: | |
| 33 | + return "This recovery phrase is not valid. Check the words and their order." | |
| 34 | + case .invalidAddress: | |
| 35 | + return "This is not a valid Ethereum address." | |
| 36 | + case .insufficientETHForGas(let need, let have): | |
| 37 | + return "Not enough of the chain's native coin to pay gas (need ~\(need), have \(have)). Gas is always paid in the native coin, never in stablecoins." | |
| 38 | + case .insufficientTokenBalance: | |
| 39 | + return "Amount exceeds your token balance." | |
| 40 | + case .rpc(let message): | |
| 41 | + return "Network error: \(message)" | |
| 42 | + case .signingFailed: | |
| 43 | + return "The transaction could not be signed." | |
| 44 | + case .internalError(let message): | |
| 45 | + return message | |
| 46 | + } | |
| 47 | + } | |
| 48 | +} | |
added
Sources/OSVaultKit/Services/BalanceService.swift
+38 −0
@@ -0,0 +1,38 @@ | ||
| 1 | +// | |
| 2 | +// BalanceService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Fetches the native ETH balance (gas money) plus every registered | |
| 13 | +/// stablecoin's `balanceOf` for the current network. | |
| 14 | +public struct Balances: Sendable { | |
| 15 | + public var ethWei: BigUInt | |
| 16 | + public var tokenUnits: [String: BigUInt] // keyed by token symbol | |
| 17 | + | |
| 18 | + public init(ethWei: BigUInt = 0, tokenUnits: [String: BigUInt] = [:]) { | |
| 19 | + self.ethWei = ethWei | |
| 20 | + self.tokenUnits = tokenUnits | |
| 21 | + } | |
| 22 | +} | |
| 23 | + | |
| 24 | +public enum BalanceService { | |
| 25 | + | |
| 26 | + public static func fetch(address: String, network: Network, rpc: RPCService) async throws -> Balances { | |
| 27 | + var balances = Balances() | |
| 28 | + balances.ethWei = try await rpc.balance(of: address) | |
| 29 | + | |
| 30 | + for token in Token.available(on: network) { | |
| 31 | + guard let contract = token.address(on: network), | |
| 32 | + let calldata = Hex.erc20BalanceOfData(owner: address) else { continue } | |
| 33 | + let result = try await rpc.call(to: contract, data: calldata) | |
| 34 | + balances.tokenUnits[token.symbol] = Hex.toBigUInt(result) ?? 0 | |
| 35 | + } | |
| 36 | + return balances | |
| 37 | + } | |
| 38 | +} | |
added
Sources/OSVaultKit/Services/BitcoinService.swift
+310 −0
@@ -0,0 +1,310 @@ | ||
| 1 | +// | |
| 2 | +// BitcoinService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | +import BitcoinDevKit | |
| 12 | + | |
| 13 | +/// Real Bitcoin support via the Bitcoin Dev Kit (bdk-swift, macOS-native). | |
| 14 | +/// | |
| 15 | +/// Same one-mnemonic model as the EVM side: BIP-84 native-segwit descriptors | |
| 16 | +/// (m/84'/…, bc1q addresses) are derived from the vault mnemonic. The service | |
| 17 | +/// holds a **watch-only** wallet (public descriptors) for sync/balance/ | |
| 18 | +/// receive; sends re-derive the secret descriptors from the vault password, | |
| 19 | +/// sign the PSBT with a throwaway in-memory signer wallet, and discard them. | |
| 20 | +/// | |
| 21 | +/// Networking is keyless Esplora (mempool.space / blockstream.info) — sync, | |
| 22 | +/// fee estimates and broadcast; endpoints follow the research in | |
| 23 | +/// docs/RESEARCH-MULTICHAIN.md. Default network is signet (testnet-first | |
| 24 | +/// rule); mainnet sits behind the same explicit switch pattern as EVM. | |
| 25 | +public actor BitcoinService { | |
| 26 | + | |
| 27 | + public enum BTCNetwork: String, CaseIterable, Codable, Sendable { | |
| 28 | + case mainnet | |
| 29 | + case signet | |
| 30 | + | |
| 31 | + public var bdkNetwork: BitcoinDevKit.Network { | |
| 32 | + switch self { | |
| 33 | + case .mainnet: return .bitcoin | |
| 34 | + case .signet: return .signet | |
| 35 | + } | |
| 36 | + } | |
| 37 | + | |
| 38 | + public var esploraURL: String { | |
| 39 | + switch self { | |
| 40 | + case .mainnet: return "https://mempool.space/api" | |
| 41 | + case .signet: return "https://mempool.space/signet/api" | |
| 42 | + } | |
| 43 | + } | |
| 44 | + | |
| 45 | + public var fallbackEsploraURL: String? { | |
| 46 | + switch self { | |
| 47 | + case .mainnet: return "https://blockstream.info/api" | |
| 48 | + case .signet: return nil | |
| 49 | + } | |
| 50 | + } | |
| 51 | + | |
| 52 | + public var feeAPI: String { | |
| 53 | + switch self { | |
| 54 | + case .mainnet: return "https://mempool.space/api/v1/fees/recommended" | |
| 55 | + case .signet: return "https://mempool.space/signet/api/v1/fees/recommended" | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | + public func explorerTxURL(_ txid: String) -> URL { | |
| 60 | + switch self { | |
| 61 | + case .mainnet: return URL(string: "https://mempool.space/tx/\(txid)")! | |
| 62 | + case .signet: return URL(string: "https://mempool.space/signet/tx/\(txid)")! | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + public func explorerAddressURL(_ address: String) -> URL { | |
| 67 | + switch self { | |
| 68 | + case .mainnet: return URL(string: "https://mempool.space/address/\(address)")! | |
| 69 | + case .signet: return URL(string: "https://mempool.space/signet/address/\(address)")! | |
| 70 | + } | |
| 71 | + } | |
| 72 | + | |
| 73 | + public var displayName: String { | |
| 74 | + switch self { | |
| 75 | + case .mainnet: return "Bitcoin" | |
| 76 | + case .signet: return "Bitcoin Signet" | |
| 77 | + } | |
| 78 | + } | |
| 79 | + | |
| 80 | + public var isTestnet: Bool { self == .signet } | |
| 81 | + } | |
| 82 | + | |
| 83 | + public static let networkKey = "osvault.bitcoin.network" | |
| 84 | + | |
| 85 | + public struct BTCBalance: Sendable { | |
| 86 | + public var confirmedSats: UInt64 = 0 | |
| 87 | + public var pendingSats: UInt64 = 0 | |
| 88 | + public var totalSats: UInt64 { confirmedSats + pendingSats } | |
| 89 | + } | |
| 90 | + | |
| 91 | + public struct FeeRates: Sendable { | |
| 92 | + public let fastest: UInt64 | |
| 93 | + public let halfHour: UInt64 | |
| 94 | + public let hour: UInt64 | |
| 95 | + public let economy: UInt64 | |
| 96 | + } | |
| 97 | + | |
| 98 | + public struct PreparedBTCSend: Sendable { | |
| 99 | + public let recipient: String | |
| 100 | + public let amountSats: UInt64 | |
| 101 | + public let feeSats: UInt64 | |
| 102 | + public let feeRateSatVb: UInt64 | |
| 103 | + public let network: BTCNetwork | |
| 104 | + } | |
| 105 | + | |
| 106 | + private var wallet: Wallet? | |
| 107 | + private var persister: Persister? | |
| 108 | + private var network: BTCNetwork = .signet | |
| 109 | + private var pendingPsbt: Psbt? | |
| 110 | + private var hasFullScanned = false | |
| 111 | + private let dataDir: URL | |
| 112 | + | |
| 113 | + public init(dataDir: URL? = nil) { | |
| 114 | + if let dataDir { | |
| 115 | + self.dataDir = dataDir | |
| 116 | + } else { | |
| 117 | + let support = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] | |
| 118 | + self.dataDir = support.appendingPathComponent("OSVault") | |
| 119 | + } | |
| 120 | + } | |
| 121 | + | |
| 122 | + // MARK: - Setup (watch-only, from the vault mnemonic) | |
| 123 | + | |
| 124 | + /// Derives BIP-84 descriptors from the mnemonic, keeps only the public | |
| 125 | + /// side, and opens (or creates) the persisted watch-only wallet. | |
| 126 | + public func configure(mnemonic: String) throws { | |
| 127 | + let stored = UserDefaults.standard.string(forKey: Self.networkKey) | |
| 128 | + network = stored.flatMap(BTCNetwork.init(rawValue:)) ?? .signet | |
| 129 | + | |
| 130 | + let (external, internalD) = try Self.publicDescriptors(mnemonic: mnemonic, network: network) | |
| 131 | + try FileManager.default.createDirectory(at: dataDir, withIntermediateDirectories: true) | |
| 132 | + let dbPath = dataDir.appendingPathComponent("bdk-\(network.rawValue).sqlite").path | |
| 133 | + | |
| 134 | + let store = try Persister.newSqlite(path: dbPath) | |
| 135 | + if let loaded = try? Wallet.load(descriptor: external, changeDescriptor: internalD, persister: store) { | |
| 136 | + wallet = loaded | |
| 137 | + } else { | |
| 138 | + wallet = try Wallet(descriptor: external, changeDescriptor: internalD, | |
| 139 | + network: network.bdkNetwork, persister: store) | |
| 140 | + } | |
| 141 | + persister = store | |
| 142 | + hasFullScanned = UserDefaults.standard.bool(forKey: scanFlagKey) | |
| 143 | + } | |
| 144 | + | |
| 145 | + private var scanFlagKey: String { "osvault.bitcoin.scanned.\(network.rawValue)" } | |
| 146 | + | |
| 147 | + static func secretDescriptors(mnemonic: String, network: BTCNetwork) throws -> (Descriptor, Descriptor) { | |
| 148 | + let parsed = try Mnemonic.fromString(mnemonic: mnemonic) | |
| 149 | + let kind: NetworkKind = network == .mainnet ? .main : .test | |
| 150 | + let key = DescriptorSecretKey(networkKind: kind, mnemonic: parsed, password: nil) | |
| 151 | + let external = Descriptor.newBip84(secretKey: key, keychainKind: .external, networkKind: kind) | |
| 152 | + let internalD = Descriptor.newBip84(secretKey: key, keychainKind: .internal, networkKind: kind) | |
| 153 | + return (external, internalD) | |
| 154 | + } | |
| 155 | + | |
| 156 | + static func publicDescriptors(mnemonic: String, network: BTCNetwork) throws -> (Descriptor, Descriptor) { | |
| 157 | + let (extSecret, intSecret) = try secretDescriptors(mnemonic: mnemonic, network: network) | |
| 158 | + // description renders the PUBLIC form of the descriptor. | |
| 159 | + let kind: NetworkKind = network == .mainnet ? .main : .test | |
| 160 | + let external = try Descriptor(descriptor: extSecret.description, networkKind: kind) | |
| 161 | + let internalD = try Descriptor(descriptor: intSecret.description, networkKind: kind) | |
| 162 | + return (external, internalD) | |
| 163 | + } | |
| 164 | + | |
| 165 | + public var isConfigured: Bool { wallet != nil } | |
| 166 | + public var currentNetwork: BTCNetwork { network } | |
| 167 | + | |
| 168 | + /// Called when the user flips mainnet/signet in Settings. | |
| 169 | + public func switchNetwork(to newNetwork: BTCNetwork, mnemonic: String) throws { | |
| 170 | + UserDefaults.standard.set(newNetwork.rawValue, forKey: Self.networkKey) | |
| 171 | + wallet = nil | |
| 172 | + persister = nil | |
| 173 | + try configure(mnemonic: mnemonic) | |
| 174 | + } | |
| 175 | + | |
| 176 | + // MARK: - Sync / balance / receive | |
| 177 | + | |
| 178 | + /// First call does a full descriptor scan (slow, once); later calls only | |
| 179 | + /// check revealed scripts (fast). | |
| 180 | + public func sync() throws { | |
| 181 | + guard let wallet, let persister else { throw WalletError.internalError("Bitcoin wallet not configured.") } | |
| 182 | + let client = EsploraClient(url: network.esploraURL) | |
| 183 | + let update: Update | |
| 184 | + if !hasFullScanned { | |
| 185 | + let request = try wallet.startFullScan().build() | |
| 186 | + update = try client.fullScan(request: request, stopGap: 20, parallelRequests: 4) | |
| 187 | + hasFullScanned = true | |
| 188 | + UserDefaults.standard.set(true, forKey: scanFlagKey) | |
| 189 | + } else { | |
| 190 | + let request = try wallet.startSyncWithRevealedSpks().build() | |
| 191 | + update = try client.sync(request: request, parallelRequests: 4) | |
| 192 | + } | |
| 193 | + try wallet.applyUpdate(update: update) | |
| 194 | + _ = try wallet.persist(persister: persister) | |
| 195 | + } | |
| 196 | + | |
| 197 | + public func balance() -> BTCBalance { | |
| 198 | + guard let wallet else { return BTCBalance() } | |
| 199 | + let b = wallet.balance() | |
| 200 | + return BTCBalance( | |
| 201 | + confirmedSats: b.confirmed.toSat(), | |
| 202 | + pendingSats: b.trustedPending.toSat() + b.untrustedPending.toSat() | |
| 203 | + ) | |
| 204 | + } | |
| 205 | + | |
| 206 | + /// Fresh address per call (privacy); the revealed index is persisted. | |
| 207 | + public func receiveAddress() throws -> String { | |
| 208 | + guard let wallet, let persister else { throw WalletError.internalError("Bitcoin wallet not configured.") } | |
| 209 | + let info = wallet.revealNextAddress(keychain: .external) | |
| 210 | + _ = try wallet.persist(persister: persister) | |
| 211 | + return info.address.description | |
| 212 | + } | |
| 213 | + | |
| 214 | + public static func validate(address: String, network: BTCNetwork) -> Bool { | |
| 215 | + (try? Address(address: address, network: network.bdkNetwork)) != nil | |
| 216 | + } | |
| 217 | + | |
| 218 | + // MARK: - Fees | |
| 219 | + | |
| 220 | + public func recommendedFees() async -> FeeRates { | |
| 221 | + var request = URLRequest(url: URL(string: network.feeAPI)!) | |
| 222 | + request.timeoutInterval = 10 | |
| 223 | + if let (data, _) = try? await URLSession.shared.data(for: request), | |
| 224 | + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Double] { | |
| 225 | + return FeeRates( | |
| 226 | + fastest: UInt64(json["fastestFee"] ?? 2), | |
| 227 | + halfHour: UInt64(json["halfHourFee"] ?? 2), | |
| 228 | + hour: UInt64(json["hourFee"] ?? 1), | |
| 229 | + economy: UInt64(json["economyFee"] ?? 1) | |
| 230 | + ) | |
| 231 | + } | |
| 232 | + return FeeRates(fastest: 3, halfHour: 2, hour: 2, economy: 1) | |
| 233 | + } | |
| 234 | + | |
| 235 | + // MARK: - Send | |
| 236 | + | |
| 237 | + /// Builds the PSBT on the watch-only wallet (coin selection, change, RBF) | |
| 238 | + /// and reports the exact fee. The PSBT is held until sign-and-broadcast. | |
| 239 | + public func prepareSend(to recipient: String, amountSats: UInt64, | |
| 240 | + feeRateSatVb: UInt64, drainAll: Bool = false) throws -> PreparedBTCSend { | |
| 241 | + guard let wallet else { throw WalletError.internalError("Bitcoin wallet not configured.") } | |
| 242 | + guard let address = try? Address(address: recipient, network: network.bdkNetwork) else { | |
| 243 | + throw WalletError.invalidAddress | |
| 244 | + } | |
| 245 | + let rate = try FeeRate.fromSatPerVb(satVb: feeRateSatVb) | |
| 246 | + var builder = TxBuilder().feeRate(feeRate: rate) | |
| 247 | + if drainAll { | |
| 248 | + builder = builder.drainWallet().drainTo(script: address.scriptPubkey()) | |
| 249 | + } else { | |
| 250 | + builder = builder.addRecipient(script: address.scriptPubkey(), | |
| 251 | + amount: Amount.fromSat(satoshi: amountSats)) | |
| 252 | + } | |
| 253 | + let psbt: Psbt | |
| 254 | + do { | |
| 255 | + psbt = try builder.finish(wallet: wallet) | |
| 256 | + } catch { | |
| 257 | + throw WalletError.internalError("Could not build the transaction: \(error.localizedDescription)") | |
| 258 | + } | |
| 259 | + pendingPsbt = psbt | |
| 260 | + let fee = (try? psbt.fee()) ?? 0 | |
| 261 | + return PreparedBTCSend( | |
| 262 | + recipient: recipient, amountSats: amountSats, | |
| 263 | + feeSats: fee, feeRateSatVb: feeRateSatVb, network: network | |
| 264 | + ) | |
| 265 | + } | |
| 266 | + | |
| 267 | + /// Signs the held PSBT with a throwaway in-memory signer wallet derived | |
| 268 | + /// from the mnemonic, broadcasts, then discards everything secret. | |
| 269 | + public func signAndBroadcast(mnemonic: String) throws -> String { | |
| 270 | + guard let wallet, let persister, let psbt = pendingPsbt else { | |
| 271 | + throw WalletError.internalError("Nothing to send.") | |
| 272 | + } | |
| 273 | + let (extSecret, intSecret) = try Self.secretDescriptors(mnemonic: mnemonic, network: network) | |
| 274 | + let signer = try Wallet(descriptor: extSecret, changeDescriptor: intSecret, | |
| 275 | + network: network.bdkNetwork, persister: Persister.newInMemory()) | |
| 276 | + let signed = try signer.sign(psbt: psbt) | |
| 277 | + guard signed else { throw WalletError.signingFailed } | |
| 278 | + | |
| 279 | + let tx = try psbt.extractTx() | |
| 280 | + let client = EsploraClient(url: network.esploraURL) | |
| 281 | + do { | |
| 282 | + try client.broadcast(transaction: tx) | |
| 283 | + } catch { | |
| 284 | + if let fallback = network.fallbackEsploraURL { | |
| 285 | + try EsploraClient(url: fallback).broadcast(transaction: tx) | |
| 286 | + } else { | |
| 287 | + throw WalletError.rpc(error.localizedDescription) | |
| 288 | + } | |
| 289 | + } | |
| 290 | + pendingPsbt = nil | |
| 291 | + // Register our own tx immediately so the balance reflects the spend. | |
| 292 | + _ = try? wallet.persist(persister: persister) | |
| 293 | + return tx.computeTxid().description | |
| 294 | + } | |
| 295 | + | |
| 296 | + public func cancelPending() { | |
| 297 | + pendingPsbt = nil | |
| 298 | + } | |
| 299 | + | |
| 300 | + // MARK: - Formatting | |
| 301 | + | |
| 302 | + public static func formatBTC(_ sats: UInt64) -> String { | |
| 303 | + TokenAmount.format(BigUInt(sats), decimals: 8) | |
| 304 | + } | |
| 305 | + | |
| 306 | + public static func parseBTC(_ input: String) -> UInt64? { | |
| 307 | + guard let units = TokenAmount.parse(input, decimals: 8), units <= BigUInt(UInt64.max) else { return nil } | |
| 308 | + return UInt64(units) | |
| 309 | + } | |
| 310 | +} | |
added
Sources/OSVaultKit/Services/KeyManager.swift
+136 −0
@@ -0,0 +1,136 @@ | ||
| 1 | +// | |
| 2 | +// KeyManager.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import Web3Core | |
| 11 | +import BigInt | |
| 12 | + | |
| 13 | +/// Wallet lifecycle: BIP-39 mnemonic generation/import, HD derivation at | |
| 14 | +/// m/44'/60'/0'/0/0, and persistence through the encrypted vault file | |
| 15 | +/// (VaultCrypto — no Keychain, no iCloud, never leaves this Mac). | |
| 16 | +/// | |
| 17 | +/// The private key is derived on demand (unlock / send / export) and returned | |
| 18 | +/// to the caller; KeyManager itself never retains key material. | |
| 19 | +public final class KeyManager { | |
| 20 | + | |
| 21 | + public static let derivationPath = "m/44'/60'/0'/0/0" | |
| 22 | + | |
| 23 | + public struct UnlockedWallet { | |
| 24 | + public let address: String // EIP-55 checksummed | |
| 25 | + public let privateKey: Data | |
| 26 | + public let mnemonic: String | |
| 27 | + } | |
| 28 | + | |
| 29 | + /// What the vault ciphertext protects. | |
| 30 | + struct VaultPayload: Codable { | |
| 31 | + let mnemonic: String | |
| 32 | + let derivationPath: String | |
| 33 | + } | |
| 34 | + | |
| 35 | + public let vaultURL: URL | |
| 36 | + | |
| 37 | + public init(vaultURL: URL? = nil) { | |
| 38 | + if let vaultURL { | |
| 39 | + self.vaultURL = vaultURL | |
| 40 | + } else { | |
| 41 | + let support = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] | |
| 42 | + self.vaultURL = support.appendingPathComponent("OSVault/vault.json") | |
| 43 | + } | |
| 44 | + } | |
| 45 | + | |
| 46 | + public var hasVault: Bool { | |
| 47 | + FileManager.default.fileExists(atPath: vaultURL.path) | |
| 48 | + } | |
| 49 | + | |
| 50 | + // MARK: - Create / import | |
| 51 | + | |
| 52 | + public func generateMnemonic() throws -> String { | |
| 53 | + guard let mnemonic = try? BIP39.generateMnemonics(bitsOfEntropy: 128, language: .english), | |
| 54 | + !mnemonic.isEmpty else { | |
| 55 | + throw WalletError.internalError("Mnemonic generation failed.") | |
| 56 | + } | |
| 57 | + return mnemonic | |
| 58 | + } | |
| 59 | + | |
| 60 | + public static func validate(mnemonic: String) -> Bool { | |
| 61 | + let words = normalize(mnemonic: mnemonic).split(separator: " ") | |
| 62 | + guard words.count == 12 || words.count == 24 else { return false } | |
| 63 | + return BIP39.mnemonicsToEntropy(normalize(mnemonic: mnemonic), language: .english) != nil | |
| 64 | + } | |
| 65 | + | |
| 66 | + /// Persists the mnemonic into a fresh encrypted vault. Same path for | |
| 67 | + /// "create" (with a just-generated mnemonic) and "import". | |
| 68 | + @discardableResult | |
| 69 | + public func saveWallet(mnemonic: String, password: String) throws -> UnlockedWallet { | |
| 70 | + let wallet = try Self.derive(mnemonic: mnemonic) | |
| 71 | + let payload = VaultPayload(mnemonic: wallet.mnemonic, derivationPath: Self.derivationPath) | |
| 72 | + let secret = try JSONEncoder().encode(payload) | |
| 73 | + let vault = try VaultCrypto.seal(secret: secret, password: password) | |
| 74 | + | |
| 75 | + let dir = vaultURL.deletingLastPathComponent() | |
| 76 | + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) | |
| 77 | + let encoder = JSONEncoder() | |
| 78 | + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] | |
| 79 | + let data = try encoder.encode(vault) | |
| 80 | + try data.write(to: vaultURL, options: [.atomic]) | |
| 81 | + try FileManager.default.setAttributes([.posixPermissions: 0o600], ofItemAtPath: vaultURL.path) | |
| 82 | + return wallet | |
| 83 | + } | |
| 84 | + | |
| 85 | + // MARK: - Unlock / export / delete | |
| 86 | + | |
| 87 | + public func unlock(password: String) throws -> UnlockedWallet { | |
| 88 | + guard hasVault else { throw WalletError.noVault } | |
| 89 | + let data: Data | |
| 90 | + do { data = try Data(contentsOf: vaultURL) } catch { throw WalletError.vaultCorrupted } | |
| 91 | + guard let vault = try? JSONDecoder().decode(VaultCrypto.VaultFile.self, from: data) else { | |
| 92 | + throw WalletError.vaultCorrupted | |
| 93 | + } | |
| 94 | + let secret = try VaultCrypto.open(vault, password: password) | |
| 95 | + guard let payload = try? JSONDecoder().decode(VaultPayload.self, from: secret) else { | |
| 96 | + throw WalletError.vaultCorrupted | |
| 97 | + } | |
| 98 | + return try Self.derive(mnemonic: payload.mnemonic) | |
| 99 | + } | |
| 100 | + | |
| 101 | + public func exportMnemonic(password: String) throws -> String { | |
| 102 | + try unlock(password: password).mnemonic | |
| 103 | + } | |
| 104 | + | |
| 105 | + public func deleteVault() throws { | |
| 106 | + guard hasVault else { return } | |
| 107 | + try FileManager.default.removeItem(at: vaultURL) | |
| 108 | + } | |
| 109 | + | |
| 110 | + // MARK: - Derivation | |
| 111 | + | |
| 112 | + public static func derive(mnemonic: String) throws -> UnlockedWallet { | |
| 113 | + let normalized = normalize(mnemonic: mnemonic) | |
| 114 | + guard validate(mnemonic: normalized), | |
| 115 | + let seed = BIP39.seedFromMmemonics(normalized, password: "", language: .english), | |
| 116 | + let root = HDNode(seed: seed), | |
| 117 | + let node = root.derive(path: derivationPath, derivePrivateKey: true), | |
| 118 | + let privateKey = node.privateKey, | |
| 119 | + let publicKey = Utilities.privateToPublic(privateKey, compressed: false), | |
| 120 | + let address = Utilities.publicToAddress(publicKey) else { | |
| 121 | + throw WalletError.invalidMnemonic | |
| 122 | + } | |
| 123 | + guard let checksummed = EthereumAddress.toChecksumAddress(address.address) else { | |
| 124 | + throw WalletError.internalError("Address derivation failed.") | |
| 125 | + } | |
| 126 | + return UnlockedWallet(address: checksummed, privateKey: privateKey, mnemonic: normalized) | |
| 127 | + } | |
| 128 | + | |
| 129 | + static func normalize(mnemonic: String) -> String { | |
| 130 | + mnemonic | |
| 131 | + .lowercased() | |
| 132 | + .components(separatedBy: .whitespacesAndNewlines) | |
| 133 | + .filter { !$0.isEmpty } | |
| 134 | + .joined(separator: " ") | |
| 135 | + } | |
| 136 | +} | |
added
Sources/OSVaultKit/Services/PriceService.swift
+129 −0
@@ -0,0 +1,129 @@ | ||
| 1 | +// | |
| 2 | +// PriceService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Fiat valuation, keyless and optional. One batched CoinGecko call covers | |
| 13 | +/// every asset in USD/CAD/EUR (research: keyless budget 5–15 calls/min; we | |
| 14 | +/// use ~1 per 2 min). Serve-stale-while-revalidate: the UI renders from the | |
| 15 | +/// on-disk cache immediately and never blocks on the network. Prices are a | |
| 16 | +/// display-layer estimate only — balances remain exact base units. | |
| 17 | +public actor PriceService { | |
| 18 | + | |
| 19 | + public static let fiatOptions = ["USD", "CAD", "EUR"] | |
| 20 | + public static let enabledKey = "osvault.prices.enabled" | |
| 21 | + public static let fiatKey = "osvault.prices.fiat" | |
| 22 | + | |
| 23 | + /// Symbol → CoinGecko id. Bridged variants share the canonical id. | |
| 24 | + static let coingeckoIDs: [String: String] = [ | |
| 25 | + "ETH": "ethereum", | |
| 26 | + "POL": "polygon-ecosystem-token", | |
| 27 | + "BNB": "binancecoin", | |
| 28 | + "AVAX": "avalanche-2", | |
| 29 | + "xDAI": "xdai", | |
| 30 | + "BTC": "bitcoin", | |
| 31 | + "SOL": "solana", | |
| 32 | + "TRX": "tron", | |
| 33 | + "XRP": "ripple", | |
| 34 | + "TON": "the-open-network", | |
| 35 | + "USDC": "usd-coin", | |
| 36 | + "USDC.e": "usd-coin", | |
| 37 | + "USDT": "tether", | |
| 38 | + "DAI": "dai", | |
| 39 | + "USDS": "usds", | |
| 40 | + "EURC": "euro-coin" | |
| 41 | + ] | |
| 42 | + | |
| 43 | + struct Cache: Codable { | |
| 44 | + var fetchedAt: Date | |
| 45 | + /// id → fiat code (lowercased) → price | |
| 46 | + var prices: [String: [String: Double]] | |
| 47 | + } | |
| 48 | + | |
| 49 | + private let cacheURL: URL | |
| 50 | + private var cache: Cache? | |
| 51 | + private let session: URLSession | |
| 52 | + private let ttl: TimeInterval = 120 | |
| 53 | + | |
| 54 | + public init(cacheURL: URL? = nil, session: URLSession = .shared) { | |
| 55 | + if let cacheURL { | |
| 56 | + self.cacheURL = cacheURL | |
| 57 | + } else { | |
| 58 | + let support = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] | |
| 59 | + self.cacheURL = support.appendingPathComponent("OSVault/prices.json") | |
| 60 | + } | |
| 61 | + self.session = session | |
| 62 | + if let data = try? Data(contentsOf: self.cacheURL), | |
| 63 | + let stored = try? JSONDecoder().decode(Cache.self, from: data) { | |
| 64 | + self.cache = stored | |
| 65 | + } | |
| 66 | + } | |
| 67 | + | |
| 68 | + /// Latest known price per symbol in `fiat`, refreshing in the background | |
| 69 | + /// when stale. Returns cached (possibly stale) values on network failure. | |
| 70 | + public func prices(for symbols: [String], fiat: String) async -> [String: Decimal] { | |
| 71 | + let ids = Set(symbols.compactMap { Self.coingeckoIDs[$0] }) | |
| 72 | + guard !ids.isEmpty else { return [:] } | |
| 73 | + | |
| 74 | + if cache == nil || Date().timeIntervalSince(cache!.fetchedAt) > ttl { | |
| 75 | + await refresh(ids: Set(Self.coingeckoIDs.values)) | |
| 76 | + } | |
| 77 | + guard let cache else { return [:] } | |
| 78 | + | |
| 79 | + var result: [String: Decimal] = [:] | |
| 80 | + for symbol in symbols { | |
| 81 | + if let id = Self.coingeckoIDs[symbol], | |
| 82 | + let value = cache.prices[id]?[fiat.lowercased()] { | |
| 83 | + result[symbol] = Decimal(value) | |
| 84 | + } | |
| 85 | + } | |
| 86 | + return result | |
| 87 | + } | |
| 88 | + | |
| 89 | + public var lastUpdated: Date? { cache?.fetchedAt } | |
| 90 | + | |
| 91 | + private func refresh(ids: Set<String>) async { | |
| 92 | + var components = URLComponents(string: "https://api.coingecko.com/api/v3/simple/price")! | |
| 93 | + components.queryItems = [ | |
| 94 | + URLQueryItem(name: "ids", value: ids.sorted().joined(separator: ",")), | |
| 95 | + URLQueryItem(name: "vs_currencies", value: "usd,cad,eur") | |
| 96 | + ] | |
| 97 | + var request = URLRequest(url: components.url!) | |
| 98 | + request.timeoutInterval = 15 | |
| 99 | + do { | |
| 100 | + let (data, response) = try await session.data(for: request) | |
| 101 | + guard let http = response as? HTTPURLResponse, http.statusCode == 200, | |
| 102 | + let json = try JSONSerialization.jsonObject(with: data) as? [String: [String: Double]] else { | |
| 103 | + return // keep stale cache | |
| 104 | + } | |
| 105 | + let fresh = Cache(fetchedAt: Date(), prices: json) | |
| 106 | + cache = fresh | |
| 107 | + let dir = cacheURL.deletingLastPathComponent() | |
| 108 | + try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) | |
| 109 | + if let encoded = try? JSONEncoder().encode(fresh) { | |
| 110 | + try? encoded.write(to: cacheURL, options: [.atomic]) | |
| 111 | + } | |
| 112 | + } catch { | |
| 113 | + // Offline or rate-limited: stale cache keeps serving. | |
| 114 | + } | |
| 115 | + } | |
| 116 | + | |
| 117 | + /// amount (base units) × price → fiat, for display only. | |
| 118 | + public static func fiatValue(units: BigUInt, decimals: Int, price: Decimal) -> Decimal { | |
| 119 | + (Decimal(string: String(units)) ?? 0) / pow(Decimal(10), decimals) * price | |
| 120 | + } | |
| 121 | + | |
| 122 | + public static func formatFiat(_ value: Decimal, currency: String) -> String { | |
| 123 | + let formatter = NumberFormatter() | |
| 124 | + formatter.numberStyle = .currency | |
| 125 | + formatter.currencyCode = currency | |
| 126 | + formatter.maximumFractionDigits = 2 | |
| 127 | + return formatter.string(from: value as NSDecimalNumber) ?? "\(value) \(currency)" | |
| 128 | + } | |
| 129 | +} | |
added
Sources/OSVaultKit/Services/RPCService.swift
+186 −0
@@ -0,0 +1,186 @@ | ||
| 1 | +// | |
| 2 | +// RPCService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Minimal JSON-RPC client over URLSession with endpoint failover: the | |
| 13 | +/// network's keyless endpoints are tried in order (user override first), a | |
| 14 | +/// failing endpoint is demoted for a cooldown, and node-side errors (reverts, | |
| 15 | +/// underpriced…) are surfaced immediately — only transport problems rotate. | |
| 16 | +/// Every method returns typed `WalletError`s; the app must never crash on RPC | |
| 17 | +/// trouble. | |
| 18 | +public actor RPCService { | |
| 19 | + | |
| 20 | + public let urls: [URL] | |
| 21 | + private let session: URLSession | |
| 22 | + private var nextID = 1 | |
| 23 | + /// Index of the endpoint that most recently worked (sticky primary). | |
| 24 | + private var preferred = 0 | |
| 25 | + private var demotedUntil: [Int: Date] = [:] | |
| 26 | + | |
| 27 | + public init(urls: [URL], session: URLSession = .shared) { | |
| 28 | + precondition(!urls.isEmpty) | |
| 29 | + self.urls = urls | |
| 30 | + self.session = session | |
| 31 | + } | |
| 32 | + | |
| 33 | + public init(url: URL, session: URLSession = .shared) { | |
| 34 | + self.init(urls: [url], session: session) | |
| 35 | + } | |
| 36 | + | |
| 37 | + // MARK: - Core request with failover | |
| 38 | + | |
| 39 | + private func orderedEndpoints() -> [Int] { | |
| 40 | + let now = Date() | |
| 41 | + let healthy = urls.indices.filter { (demotedUntil[$0] ?? .distantPast) < now } | |
| 42 | + let demoted = urls.indices.filter { !healthy.contains($0) } | |
| 43 | + let sorted = healthy.sorted { a, b in | |
| 44 | + (a == preferred ? 0 : 1, a) < (b == preferred ? 0 : 1, b) | |
| 45 | + } | |
| 46 | + return sorted + demoted // demoted endpoints remain the last resort | |
| 47 | + } | |
| 48 | + | |
| 49 | + private func request(method: String, params: [Any]) async throws -> Any { | |
| 50 | + let id = nextID | |
| 51 | + nextID += 1 | |
| 52 | + let body: [String: Any] = ["jsonrpc": "2.0", "id": id, "method": method, "params": params] | |
| 53 | + let payload = try JSONSerialization.data(withJSONObject: body) | |
| 54 | + | |
| 55 | + var lastError: Error = WalletError.rpc("Unreachable RPC endpoint.") | |
| 56 | + for index in orderedEndpoints() { | |
| 57 | + var req = URLRequest(url: urls[index]) | |
| 58 | + req.httpMethod = "POST" | |
| 59 | + req.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
| 60 | + req.httpBody = payload | |
| 61 | + req.timeoutInterval = 15 | |
| 62 | + | |
| 63 | + for attempt in 0..<2 { | |
| 64 | + if attempt > 0 { | |
| 65 | + try? await Task.sleep(nanoseconds: 500_000_000) | |
| 66 | + } | |
| 67 | + do { | |
| 68 | + let (data, response) = try await session.data(for: req) | |
| 69 | + if let http = response as? HTTPURLResponse, !(200...299).contains(http.statusCode) { | |
| 70 | + lastError = WalletError.rpc("HTTP \(http.statusCode) from RPC endpoint.") | |
| 71 | + continue | |
| 72 | + } | |
| 73 | + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { | |
| 74 | + lastError = WalletError.rpc("Malformed RPC response.") | |
| 75 | + continue | |
| 76 | + } | |
| 77 | + if let errorDict = json["error"] as? [String: Any] { | |
| 78 | + let message = (errorDict["message"] as? String) ?? "RPC error" | |
| 79 | + let code = errorDict["code"] as? Int ?? 0 | |
| 80 | + // Rate-limit style errors → try the next endpoint; | |
| 81 | + // genuine node-side errors (revert, nonce, funds) are | |
| 82 | + // not transient and must surface immediately. | |
| 83 | + if code == -32005 || code == -32001 || message.lowercased().contains("rate") { | |
| 84 | + lastError = WalletError.rpc(message) | |
| 85 | + break | |
| 86 | + } | |
| 87 | + throw WalletError.rpc(message) | |
| 88 | + } | |
| 89 | + guard let result = json["result"] else { | |
| 90 | + lastError = WalletError.rpc("RPC response missing result.") | |
| 91 | + continue | |
| 92 | + } | |
| 93 | + preferred = index | |
| 94 | + return result | |
| 95 | + } catch let error as WalletError { | |
| 96 | + throw error | |
| 97 | + } catch { | |
| 98 | + lastError = WalletError.rpc(error.localizedDescription) | |
| 99 | + } | |
| 100 | + } | |
| 101 | + demotedUntil[index] = Date().addingTimeInterval(60) | |
| 102 | + } | |
| 103 | + throw lastError | |
| 104 | + } | |
| 105 | + | |
| 106 | + private func quantity(method: String, params: [Any]) async throws -> BigUInt { | |
| 107 | + guard let hex = try await request(method: method, params: params) as? String, | |
| 108 | + let value = Hex.toBigUInt(hex) else { | |
| 109 | + throw WalletError.rpc("Unexpected result for \(method).") | |
| 110 | + } | |
| 111 | + return value | |
| 112 | + } | |
| 113 | + | |
| 114 | + // MARK: - Ethereum methods | |
| 115 | + | |
| 116 | + public func chainID() async throws -> BigUInt { | |
| 117 | + try await quantity(method: "eth_chainId", params: []) | |
| 118 | + } | |
| 119 | + | |
| 120 | + public func balance(of address: String) async throws -> BigUInt { | |
| 121 | + try await quantity(method: "eth_getBalance", params: [address, "latest"]) | |
| 122 | + } | |
| 123 | + | |
| 124 | + public func call(to contract: String, data: Data) async throws -> String { | |
| 125 | + guard let result = try await request( | |
| 126 | + method: "eth_call", | |
| 127 | + params: [["to": contract, "data": Hex.string(data)], "latest"] | |
| 128 | + ) as? String else { | |
| 129 | + throw WalletError.rpc("Unexpected result for eth_call.") | |
| 130 | + } | |
| 131 | + return result | |
| 132 | + } | |
| 133 | + | |
| 134 | + public func transactionCount(of address: String) async throws -> BigUInt { | |
| 135 | + try await quantity(method: "eth_getTransactionCount", params: [address, "pending"]) | |
| 136 | + } | |
| 137 | + | |
| 138 | + public func estimateGas(from: String, to destination: String, valueWei: BigUInt, data: Data) async throws -> BigUInt { | |
| 139 | + var tx: [String: Any] = ["from": from, "to": destination] | |
| 140 | + if valueWei > 0 { tx["value"] = Hex.quantity(valueWei) } | |
| 141 | + if !data.isEmpty { tx["data"] = Hex.string(data) } | |
| 142 | + return try await quantity(method: "eth_estimateGas", params: [tx]) | |
| 143 | + } | |
| 144 | + | |
| 145 | + public func gasPrice() async throws -> BigUInt { | |
| 146 | + try await quantity(method: "eth_gasPrice", params: []) | |
| 147 | + } | |
| 148 | + | |
| 149 | + public func maxPriorityFeePerGas() async throws -> BigUInt { | |
| 150 | + try await quantity(method: "eth_maxPriorityFeePerGas", params: []) | |
| 151 | + } | |
| 152 | + | |
| 153 | + public func latestBaseFee() async throws -> BigUInt { | |
| 154 | + guard let block = try await request(method: "eth_getBlockByNumber", params: ["latest", false]) as? [String: Any], | |
| 155 | + let hex = block["baseFeePerGas"] as? String, | |
| 156 | + let fee = Hex.toBigUInt(hex) else { | |
| 157 | + throw WalletError.rpc("Latest block has no base fee.") | |
| 158 | + } | |
| 159 | + return fee | |
| 160 | + } | |
| 161 | + | |
| 162 | + public func sendRawTransaction(_ rawHex: String) async throws -> String { | |
| 163 | + guard let hash = try await request(method: "eth_sendRawTransaction", params: [rawHex]) as? String else { | |
| 164 | + throw WalletError.rpc("Broadcast returned no transaction hash.") | |
| 165 | + } | |
| 166 | + return hash | |
| 167 | + } | |
| 168 | + | |
| 169 | + public struct Receipt { | |
| 170 | + public let succeeded: Bool | |
| 171 | + public let blockNumber: BigUInt? | |
| 172 | + } | |
| 173 | + | |
| 174 | + /// nil while the transaction is still pending. | |
| 175 | + public func transactionReceipt(_ hash: String) async throws -> Receipt? { | |
| 176 | + let result = try await request(method: "eth_getTransactionReceipt", params: [hash]) | |
| 177 | + if result is NSNull { return nil } | |
| 178 | + guard let dict = result as? [String: Any], let statusHex = dict["status"] as? String else { | |
| 179 | + return nil | |
| 180 | + } | |
| 181 | + return Receipt( | |
| 182 | + succeeded: Hex.toBigUInt(statusHex) == 1, | |
| 183 | + blockNumber: (dict["blockNumber"] as? String).flatMap(Hex.toBigUInt) | |
| 184 | + ) | |
| 185 | + } | |
| 186 | +} | |
added
Sources/OSVaultKit/Services/SolanaService.swift
+263 −0
@@ -0,0 +1,263 @@ | ||
| 1 | +// | |
| 2 | +// SolanaService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import SolanaSwift | |
| 11 | + | |
| 12 | +/// Solana support via solana-swift (macOS-native, maintained — see | |
| 13 | +/// docs/RESEARCH-MULTICHAIN.md): SOL + USDC (SPL) from the same vault | |
| 14 | +/// mnemonic, ed25519 at m/44'/501'/0'/0' (Phantom-compatible bip44Change). | |
| 15 | +/// | |
| 16 | +/// Security model matches the rest of the app: only the public address stays | |
| 17 | +/// in memory; sends re-derive the keypair from the vault password, sign, and | |
| 18 | +/// discard. RPC is keyless (PublicNode mainnet / official devnet). Default | |
| 19 | +/// network is devnet (testnet-first rule). | |
| 20 | +public actor SolanaService { | |
| 21 | + | |
| 22 | + public enum SOLNetwork: String, CaseIterable, Codable, Sendable { | |
| 23 | + case mainnet | |
| 24 | + case devnet | |
| 25 | + | |
| 26 | + var solanaNetwork: SolanaSwift.Network { | |
| 27 | + switch self { | |
| 28 | + case .mainnet: return .mainnetBeta | |
| 29 | + case .devnet: return .devnet | |
| 30 | + } | |
| 31 | + } | |
| 32 | + | |
| 33 | + public var rpcURL: String { | |
| 34 | + switch self { | |
| 35 | + // PublicNode: keyless, MEV-protected; official endpoint fallback. | |
| 36 | + case .mainnet: return "https://solana-rpc.publicnode.com" | |
| 37 | + case .devnet: return "https://api.devnet.solana.com" | |
| 38 | + } | |
| 39 | + } | |
| 40 | + | |
| 41 | + var fallbackRPCURL: String? { | |
| 42 | + switch self { | |
| 43 | + case .mainnet: return "https://api.mainnet-beta.solana.com" | |
| 44 | + case .devnet: return nil | |
| 45 | + } | |
| 46 | + } | |
| 47 | + | |
| 48 | + /// Circle-issued USDC mint (devnet mint is the Circle faucet's). | |
| 49 | + public var usdcMint: String { | |
| 50 | + switch self { | |
| 51 | + case .mainnet: return "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" | |
| 52 | + case .devnet: return "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU" | |
| 53 | + } | |
| 54 | + } | |
| 55 | + | |
| 56 | + public func explorerTxURL(_ signature: String) -> URL { | |
| 57 | + switch self { | |
| 58 | + case .mainnet: return URL(string: "https://explorer.solana.com/tx/\(signature)")! | |
| 59 | + case .devnet: return URL(string: "https://explorer.solana.com/tx/\(signature)?cluster=devnet")! | |
| 60 | + } | |
| 61 | + } | |
| 62 | + | |
| 63 | + public func explorerAddressURL(_ address: String) -> URL { | |
| 64 | + switch self { | |
| 65 | + case .mainnet: return URL(string: "https://explorer.solana.com/address/\(address)")! | |
| 66 | + case .devnet: return URL(string: "https://explorer.solana.com/address/\(address)?cluster=devnet")! | |
| 67 | + } | |
| 68 | + } | |
| 69 | + | |
| 70 | + public var displayName: String { | |
| 71 | + switch self { | |
| 72 | + case .mainnet: return "Solana" | |
| 73 | + case .devnet: return "Solana Devnet" | |
| 74 | + } | |
| 75 | + } | |
| 76 | + | |
| 77 | + public var isTestnet: Bool { self == .devnet } | |
| 78 | + } | |
| 79 | + | |
| 80 | + public static let networkKey = "osvault.solana.network" | |
| 81 | + public static let usdcDecimals = 6 | |
| 82 | + static let derivablePath = DerivablePath(type: .bip44Change, walletIndex: 0, accountIndex: 0) | |
| 83 | + | |
| 84 | + public struct SOLBalances: Sendable { | |
| 85 | + public var lamports: UInt64 = 0 // SOL, 9 decimals | |
| 86 | + public var usdcUnits: UInt64 = 0 // USDC, 6 decimals | |
| 87 | + } | |
| 88 | + | |
| 89 | + public struct PreparedSOLSend: Sendable { | |
| 90 | + public let recipient: String | |
| 91 | + public let amountUnits: UInt64 | |
| 92 | + public let isUSDC: Bool | |
| 93 | + /// Signature fee + ATA rent if the recipient needs a token account. | |
| 94 | + public let estimatedFeeLamports: UInt64 | |
| 95 | + public let createsTokenAccount: Bool | |
| 96 | + public let network: SOLNetwork | |
| 97 | + } | |
| 98 | + | |
| 99 | + private var address: String? | |
| 100 | + private var network: SOLNetwork = .devnet | |
| 101 | + | |
| 102 | + // MARK: - Setup | |
| 103 | + | |
| 104 | + public func configure(mnemonic: String) async throws { | |
| 105 | + let stored = UserDefaults.standard.string(forKey: Self.networkKey) | |
| 106 | + network = stored.flatMap(SOLNetwork.init(rawValue:)) ?? .devnet | |
| 107 | + let keyPair = try await Self.deriveKeyPair(mnemonic: mnemonic, network: network) | |
| 108 | + address = keyPair.publicKey.base58EncodedString | |
| 109 | + } | |
| 110 | + | |
| 111 | + static func deriveKeyPair(mnemonic: String, network: SOLNetwork) async throws -> KeyPair { | |
| 112 | + try await KeyPair( | |
| 113 | + phrase: mnemonic.split(separator: " ").map(String.init), | |
| 114 | + network: network.solanaNetwork, | |
| 115 | + derivablePath: derivablePath | |
| 116 | + ) | |
| 117 | + } | |
| 118 | + | |
| 119 | + public var isConfigured: Bool { address != nil } | |
| 120 | + public var currentNetwork: SOLNetwork { network } | |
| 121 | + public var publicAddress: String? { address } | |
| 122 | + | |
| 123 | + /// The address is derivation-only, so switching clusters needs no password. | |
| 124 | + public func switchNetwork(to newNetwork: SOLNetwork) { | |
| 125 | + UserDefaults.standard.set(newNetwork.rawValue, forKey: Self.networkKey) | |
| 126 | + network = newNetwork | |
| 127 | + } | |
| 128 | + | |
| 129 | + public static func validate(address: String) -> Bool { | |
| 130 | + // solana-swift's PublicKey(string:) is lax; enforce strict base58 | |
| 131 | + // alphabet and an exact 32-byte decode. | |
| 132 | + guard address.count >= 32, address.count <= 44, | |
| 133 | + address.allSatisfy({ "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".contains($0) }), | |
| 134 | + Base58.decode(address).count == 32 else { | |
| 135 | + return false | |
| 136 | + } | |
| 137 | + return true | |
| 138 | + } | |
| 139 | + | |
| 140 | + // MARK: - RPC | |
| 141 | + | |
| 142 | + private func apiClient() -> JSONRPCAPIClient { | |
| 143 | + JSONRPCAPIClient(endpoint: APIEndPoint(address: network.rpcURL, network: network.solanaNetwork)) | |
| 144 | + } | |
| 145 | + | |
| 146 | + private func fallbackClient() -> JSONRPCAPIClient? { | |
| 147 | + network.fallbackRPCURL.map { | |
| 148 | + JSONRPCAPIClient(endpoint: APIEndPoint(address: $0, network: network.solanaNetwork)) | |
| 149 | + } | |
| 150 | + } | |
| 151 | + | |
| 152 | + private func usdcATA() throws -> PublicKey { | |
| 153 | + guard let address else { throw WalletError.internalError("Solana not configured.") } | |
| 154 | + return try PublicKey.associatedTokenAddress( | |
| 155 | + walletAddress: PublicKey(string: address), | |
| 156 | + tokenMintAddress: PublicKey(string: network.usdcMint), | |
| 157 | + tokenProgramId: TokenProgram.id | |
| 158 | + ) | |
| 159 | + } | |
| 160 | + | |
| 161 | + // MARK: - Balances | |
| 162 | + | |
| 163 | + public func fetchBalances() async throws -> SOLBalances { | |
| 164 | + guard let address else { throw WalletError.internalError("Solana not configured.") } | |
| 165 | + let client = apiClient() | |
| 166 | + var balances = SOLBalances() | |
| 167 | + do { | |
| 168 | + balances.lamports = try await client.getBalance(account: address, commitment: "confirmed") | |
| 169 | + } catch { | |
| 170 | + guard let fallback = fallbackClient() else { throw WalletError.rpc(error.localizedDescription) } | |
| 171 | + balances.lamports = try await fallback.getBalance(account: address, commitment: "confirmed") | |
| 172 | + } | |
| 173 | + if let ata = try? usdcATA(), | |
| 174 | + let tokenBalance = try? await client.getTokenAccountBalance( | |
| 175 | + pubkey: ata.base58EncodedString, commitment: "confirmed"), | |
| 176 | + let units = UInt64(tokenBalance.amount) { | |
| 177 | + balances.usdcUnits = units | |
| 178 | + } | |
| 179 | + return balances | |
| 180 | + } | |
| 181 | + | |
| 182 | + // MARK: - Send | |
| 183 | + | |
| 184 | + /// Fee estimate without touching key material: signature fee + ATA rent | |
| 185 | + /// when sending USDC to a wallet that has no token account yet (the | |
| 186 | + /// sender funds ~0.002 SOL of rent — a Solana-specific gotcha). | |
| 187 | + public func estimateSend(to recipient: String, amountUnits: UInt64, isUSDC: Bool) async throws -> PreparedSOLSend { | |
| 188 | + guard Self.validate(address: recipient) else { throw WalletError.invalidAddress } | |
| 189 | + let client = apiClient() | |
| 190 | + let lamportsPerSignature: UInt64 = 5_000 | |
| 191 | + var createsATA = false | |
| 192 | + var fee = lamportsPerSignature | |
| 193 | + if isUSDC { | |
| 194 | + let recipientATA = try PublicKey.associatedTokenAddress( | |
| 195 | + walletAddress: PublicKey(string: recipient), | |
| 196 | + tokenMintAddress: PublicKey(string: network.usdcMint), | |
| 197 | + tokenProgramId: TokenProgram.id | |
| 198 | + ) | |
| 199 | + let info: BufferInfo<TokenAccountState>? = try? await client.getAccountInfo( | |
| 200 | + account: recipientATA.base58EncodedString) | |
| 201 | + if info == nil { | |
| 202 | + createsATA = true | |
| 203 | + let rent = (try? await client.getMinimumBalanceForRentExemption( | |
| 204 | + dataLength: 165, commitment: "confirmed")) ?? 2_039_280 | |
| 205 | + fee += rent | |
| 206 | + } | |
| 207 | + } | |
| 208 | + return PreparedSOLSend( | |
| 209 | + recipient: recipient, amountUnits: amountUnits, isUSDC: isUSDC, | |
| 210 | + estimatedFeeLamports: fee, createsTokenAccount: createsATA, network: network | |
| 211 | + ) | |
| 212 | + } | |
| 213 | + | |
| 214 | + /// Derives the keypair from the mnemonic, builds + signs + broadcasts, | |
| 215 | + /// returns the transaction signature. Key material is never retained. | |
| 216 | + public func send(_ prepared: PreparedSOLSend, mnemonic: String) async throws -> String { | |
| 217 | + let account = try await Self.deriveKeyPair(mnemonic: mnemonic, network: network) | |
| 218 | + let client = apiClient() | |
| 219 | + let blockchain = BlockchainClient(apiClient: client) | |
| 220 | + | |
| 221 | + if prepared.isUSDC { | |
| 222 | + let sourceATA = try usdcATA() | |
| 223 | + let lamportsPerSignature: UInt64 = 5_000 | |
| 224 | + let minRent = (try? await client.getMinimumBalanceForRentExemption( | |
| 225 | + dataLength: 165, commitment: "confirmed")) ?? 2_039_280 | |
| 226 | + let (tx, _) = try await blockchain.prepareSendingSPLTokens( | |
| 227 | + account: account, | |
| 228 | + mintAddress: network.usdcMint, | |
| 229 | + tokenProgramId: TokenProgram.id, | |
| 230 | + decimals: UInt8(Self.usdcDecimals), | |
| 231 | + from: sourceATA.base58EncodedString, | |
| 232 | + to: prepared.recipient, | |
| 233 | + amount: prepared.amountUnits, | |
| 234 | + lamportsPerSignature: lamportsPerSignature, | |
| 235 | + minRentExemption: minRent | |
| 236 | + ) | |
| 237 | + return try await blockchain.sendTransaction(preparedTransaction: tx) | |
| 238 | + } else { | |
| 239 | + let tx = try await blockchain.prepareSendingNativeSOL( | |
| 240 | + from: account, | |
| 241 | + to: prepared.recipient, | |
| 242 | + amount: prepared.amountUnits | |
| 243 | + ) | |
| 244 | + return try await blockchain.sendTransaction(preparedTransaction: tx) | |
| 245 | + } | |
| 246 | + } | |
| 247 | + | |
| 248 | + // MARK: - Formatting | |
| 249 | + | |
| 250 | + public static func formatSOL(_ lamports: UInt64) -> String { | |
| 251 | + TokenAmount.format(.init(lamports), decimals: 9, maxFractionDigits: 6) | |
| 252 | + } | |
| 253 | + | |
| 254 | + public static func parseSOL(_ input: String) -> UInt64? { | |
| 255 | + guard let units = TokenAmount.parse(input, decimals: 9), units <= .init(UInt64.max) else { return nil } | |
| 256 | + return UInt64(units) | |
| 257 | + } | |
| 258 | + | |
| 259 | + public static func parseUSDC(_ input: String) -> UInt64? { | |
| 260 | + guard let units = TokenAmount.parse(input, decimals: usdcDecimals), units <= .init(UInt64.max) else { return nil } | |
| 261 | + return UInt64(units) | |
| 262 | + } | |
| 263 | +} | |
added
Sources/OSVaultKit/Services/TONService.swift
+297 −0
@@ -0,0 +1,297 @@ | ||
| 1 | +// | |
| 2 | +// TONService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | +import WalletCore | |
| 12 | + | |
| 13 | +/// TON support: native TON + USDT (jetton, TEP-74). Signing via wallet-core | |
| 14 | +/// (`Transfer` / `JettonTransfer`, wallet v4R2 — the address format | |
| 15 | +/// wallet-core derives). Networking via keyless toncenter (v2 for wallet | |
| 16 | +/// state and broadcast, v3 for jetton wallets), throttled to its documented | |
| 17 | +/// 1 req/s anonymous budget. | |
| 18 | +/// | |
| 19 | +/// TON specifics: jetton balances live in a separate jetton-wallet contract; | |
| 20 | +/// a jetton transfer is a TON message to YOUR jetton wallet carrying | |
| 21 | +/// ~0.07 TON for fees (excess refunded). The wallet contract itself deploys | |
| 22 | +/// with the first outgoing transfer (seqno 0 → wallet-core adds stateInit). | |
| 23 | +public actor TONService { | |
| 24 | + | |
| 25 | + public enum TONNetwork: String, CaseIterable, Codable, Sendable { | |
| 26 | + case mainnet | |
| 27 | + case testnet | |
| 28 | + | |
| 29 | + public var v2Base: String { | |
| 30 | + switch self { | |
| 31 | + case .mainnet: return "https://toncenter.com/api/v2" | |
| 32 | + case .testnet: return "https://testnet.toncenter.com/api/v2" | |
| 33 | + } | |
| 34 | + } | |
| 35 | + | |
| 36 | + public var v3Base: String { | |
| 37 | + switch self { | |
| 38 | + case .mainnet: return "https://toncenter.com/api/v3" | |
| 39 | + case .testnet: return "https://testnet.toncenter.com/api/v3" | |
| 40 | + } | |
| 41 | + } | |
| 42 | + | |
| 43 | + /// Tether-issued USDT jetton master (mainnet only; no official | |
| 44 | + /// testnet USDT). | |
| 45 | + public var usdtMaster: String? { | |
| 46 | + switch self { | |
| 47 | + case .mainnet: return "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs" | |
| 48 | + case .testnet: return nil | |
| 49 | + } | |
| 50 | + } | |
| 51 | + | |
| 52 | + public func explorerTxURL(_ hash: String) -> URL { | |
| 53 | + switch self { | |
| 54 | + case .mainnet: return URL(string: "https://tonviewer.com/transaction/\(hash)")! | |
| 55 | + case .testnet: return URL(string: "https://testnet.tonviewer.com/transaction/\(hash)")! | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | + public func explorerAddressURL(_ address: String) -> URL { | |
| 60 | + switch self { | |
| 61 | + case .mainnet: return URL(string: "https://tonviewer.com/\(address)")! | |
| 62 | + case .testnet: return URL(string: "https://testnet.tonviewer.com/\(address)")! | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + public var displayName: String { | |
| 67 | + switch self { | |
| 68 | + case .mainnet: return "TON" | |
| 69 | + case .testnet: return "TON Testnet" | |
| 70 | + } | |
| 71 | + } | |
| 72 | + | |
| 73 | + public var isTestnet: Bool { self == .testnet } | |
| 74 | + } | |
| 75 | + | |
| 76 | + public static let networkKey = "osvault.ton.network" | |
| 77 | + public static let tonDecimals = 9 | |
| 78 | + public static let usdtDecimals = 6 | |
| 79 | + /// TON attached to a jetton transfer for fees (excess refunded). | |
| 80 | + static let jettonAttachNanotons: UInt64 = 70_000_000 // 0.07 TON | |
| 81 | + static let sendMode: UInt32 = 3 // pay fees separately + ignore errors | |
| 82 | + | |
| 83 | + public struct TONBalances: Sendable { | |
| 84 | + public var nanotons: UInt64 = 0 | |
| 85 | + public var usdtUnits: UInt64 = 0 | |
| 86 | + public var deployed = false | |
| 87 | + } | |
| 88 | + | |
| 89 | + public struct PreparedTONSend: Sendable { | |
| 90 | + public let recipient: String | |
| 91 | + public let amountUnits: UInt64 | |
| 92 | + public let isUSDT: Bool | |
| 93 | + public let estimatedFeeNanotons: UInt64 | |
| 94 | + public let network: TONNetwork | |
| 95 | + } | |
| 96 | + | |
| 97 | + private var address: String? | |
| 98 | + private var network: TONNetwork = .testnet | |
| 99 | + private var lastRequest = Date.distantPast | |
| 100 | + | |
| 101 | + // MARK: - Setup | |
| 102 | + | |
| 103 | + public func configure(mnemonic: String) throws { | |
| 104 | + let stored = UserDefaults.standard.string(forKey: Self.networkKey) | |
| 105 | + network = stored.flatMap(TONNetwork.init(rawValue:)) ?? .testnet | |
| 106 | + guard let wallet = HDWallet(mnemonic: mnemonic, passphrase: "") else { | |
| 107 | + throw WalletError.invalidMnemonic | |
| 108 | + } | |
| 109 | + address = wallet.getAddressForCoin(coin: .ton) | |
| 110 | + } | |
| 111 | + | |
| 112 | + public var isConfigured: Bool { address != nil } | |
| 113 | + public var currentNetwork: TONNetwork { network } | |
| 114 | + public var publicAddress: String? { address } | |
| 115 | + | |
| 116 | + public func switchNetwork(to newNetwork: TONNetwork) { | |
| 117 | + UserDefaults.standard.set(newNetwork.rawValue, forKey: Self.networkKey) | |
| 118 | + network = newNetwork | |
| 119 | + } | |
| 120 | + | |
| 121 | + public static func validate(address: String) -> Bool { | |
| 122 | + AnyAddress.isValid(string: address, coin: .ton) | |
| 123 | + } | |
| 124 | + | |
| 125 | + // MARK: - HTTP (1 req/s budget) | |
| 126 | + | |
| 127 | + private func throttle() async { | |
| 128 | + let elapsed = Date().timeIntervalSince(lastRequest) | |
| 129 | + if elapsed < 1.1 { | |
| 130 | + try? await Task.sleep(nanoseconds: UInt64((1.1 - elapsed) * 1_000_000_000)) | |
| 131 | + } | |
| 132 | + lastRequest = Date() | |
| 133 | + } | |
| 134 | + | |
| 135 | + private func getJSON(_ url: URL) async throws -> [String: Any] { | |
| 136 | + await throttle() | |
| 137 | + var request = URLRequest(url: url) | |
| 138 | + request.timeoutInterval = 20 | |
| 139 | + let (data, _) = try await URLSession.shared.data(for: request) | |
| 140 | + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { | |
| 141 | + throw WalletError.rpc("Malformed toncenter response.") | |
| 142 | + } | |
| 143 | + return json | |
| 144 | + } | |
| 145 | + | |
| 146 | + // MARK: - Balances | |
| 147 | + | |
| 148 | + public func fetchBalances() async throws -> TONBalances { | |
| 149 | + guard let address else { throw WalletError.internalError("TON not configured.") } | |
| 150 | + var balances = TONBalances() | |
| 151 | + | |
| 152 | + var components = URLComponents(string: network.v2Base + "/getWalletInformation")! | |
| 153 | + components.queryItems = [URLQueryItem(name: "address", value: address)] | |
| 154 | + let info = try await getJSON(components.url!) | |
| 155 | + guard info["ok"] as? Bool == true, let result = info["result"] as? [String: Any] else { | |
| 156 | + throw WalletError.rpc((info["error"] as? String) ?? "toncenter query failed.") | |
| 157 | + } | |
| 158 | + balances.nanotons = (result["balance"] as? String).flatMap(UInt64.init) | |
| 159 | + ?? (result["balance"] as? NSNumber)?.uint64Value ?? 0 | |
| 160 | + balances.deployed = (result["account_state"] as? String) == "active" | |
| 161 | + | |
| 162 | + if let master = network.usdtMaster { | |
| 163 | + var jettonComponents = URLComponents(string: network.v3Base + "/jetton/wallets")! | |
| 164 | + jettonComponents.queryItems = [ | |
| 165 | + URLQueryItem(name: "owner_address", value: address), | |
| 166 | + URLQueryItem(name: "jetton_address", value: master), | |
| 167 | + URLQueryItem(name: "limit", value: "1") | |
| 168 | + ] | |
| 169 | + if let json = try? await getJSON(jettonComponents.url!), | |
| 170 | + let wallets = json["jetton_wallets"] as? [[String: Any]], | |
| 171 | + let first = wallets.first, | |
| 172 | + let balance = first["balance"] as? String, let units = UInt64(balance) { | |
| 173 | + balances.usdtUnits = units | |
| 174 | + } | |
| 175 | + } | |
| 176 | + return balances | |
| 177 | + } | |
| 178 | + | |
| 179 | + /// Raw-format jetton wallet address (0:hex) for this owner, if any. | |
| 180 | + private func myJettonWallet() async throws -> String? { | |
| 181 | + guard let address, let master = network.usdtMaster else { return nil } | |
| 182 | + var components = URLComponents(string: network.v3Base + "/jetton/wallets")! | |
| 183 | + components.queryItems = [ | |
| 184 | + URLQueryItem(name: "owner_address", value: address), | |
| 185 | + URLQueryItem(name: "jetton_address", value: master), | |
| 186 | + URLQueryItem(name: "limit", value: "1") | |
| 187 | + ] | |
| 188 | + let json = try await getJSON(components.url!) | |
| 189 | + guard let wallets = json["jetton_wallets"] as? [[String: Any]], | |
| 190 | + let raw = wallets.first?["address"] as? String else { return nil } | |
| 191 | + // Convert raw 0:hex to the user-friendly bounceable form for the tx. | |
| 192 | + return TONAddressConverter.toUserFriendly(address: raw, bounceable: true, testnet: network.isTestnet) | |
| 193 | + } | |
| 194 | + | |
| 195 | + // MARK: - Estimate | |
| 196 | + | |
| 197 | + public func estimateSend(to recipient: String, amountUnits: UInt64, isUSDT: Bool) async throws -> PreparedTONSend { | |
| 198 | + guard Self.validate(address: recipient) else { throw WalletError.invalidAddress } | |
| 199 | + if isUSDT { | |
| 200 | + guard network.usdtMaster != nil else { | |
| 201 | + throw WalletError.internalError("USDT is not available on TON testnet.") | |
| 202 | + } | |
| 203 | + guard try await myJettonWallet() != nil else { | |
| 204 | + throw WalletError.internalError("No USDT jetton wallet found for this account (balance is 0).") | |
| 205 | + } | |
| 206 | + } | |
| 207 | + // Typical costs: plain transfer ~0.004 TON; jetton carries the | |
| 208 | + // attached 0.07 TON of which the unused part is refunded. | |
| 209 | + let fee: UInt64 = isUSDT ? Self.jettonAttachNanotons : 5_000_000 | |
| 210 | + return PreparedTONSend( | |
| 211 | + recipient: recipient, amountUnits: amountUnits, | |
| 212 | + isUSDT: isUSDT, estimatedFeeNanotons: fee, network: network | |
| 213 | + ) | |
| 214 | + } | |
| 215 | + | |
| 216 | + // MARK: - Sign + broadcast | |
| 217 | + | |
| 218 | + public func send(_ prepared: PreparedTONSend, mnemonic: String) async throws -> String { | |
| 219 | + guard let address else { throw WalletError.internalError("TON not configured.") } | |
| 220 | + guard let wallet = HDWallet(mnemonic: mnemonic, passphrase: "") else { | |
| 221 | + throw WalletError.invalidMnemonic | |
| 222 | + } | |
| 223 | + | |
| 224 | + // seqno (0 for an undeployed wallet → wallet-core adds stateInit). | |
| 225 | + var components = URLComponents(string: network.v2Base + "/getWalletInformation")! | |
| 226 | + components.queryItems = [URLQueryItem(name: "address", value: address)] | |
| 227 | + let info = try await getJSON(components.url!) | |
| 228 | + let result = info["result"] as? [String: Any] ?? [:] | |
| 229 | + let seqno = (result["seqno"] as? NSNumber)?.uint32Value ?? 0 | |
| 230 | + | |
| 231 | + var transfer = TheOpenNetworkTransfer() | |
| 232 | + transfer.mode = Self.sendMode | |
| 233 | + if prepared.isUSDT { | |
| 234 | + guard let jettonWallet = try await myJettonWallet() else { | |
| 235 | + throw WalletError.internalError("USDT jetton wallet not found.") | |
| 236 | + } | |
| 237 | + transfer.dest = jettonWallet | |
| 238 | + transfer.amount = BigUInt(Self.jettonAttachNanotons).serialize() | |
| 239 | + transfer.bounceable = true | |
| 240 | + var jetton = TheOpenNetworkJettonTransfer() | |
| 241 | + jetton.jettonAmount = BigUInt(prepared.amountUnits).serialize() | |
| 242 | + jetton.toOwner = prepared.recipient | |
| 243 | + jetton.responseAddress = address | |
| 244 | + jetton.forwardAmount = BigUInt(1).serialize() | |
| 245 | + transfer.payload = .jettonTransfer(jetton) | |
| 246 | + } else { | |
| 247 | + transfer.dest = prepared.recipient | |
| 248 | + transfer.amount = BigUInt(prepared.amountUnits).serialize() | |
| 249 | + transfer.bounceable = false // wallets use non-bounceable | |
| 250 | + } | |
| 251 | + | |
| 252 | + let key = wallet.getKeyForCoin(coin: .ton) | |
| 253 | + var input = TheOpenNetworkSigningInput() | |
| 254 | + input.privateKey = key.data | |
| 255 | + input.walletVersion = .walletV4R2 | |
| 256 | + input.sequenceNumber = seqno | |
| 257 | + input.expireAt = UInt32(Date().timeIntervalSince1970) + 300 | |
| 258 | + input.messages = [transfer] | |
| 259 | + | |
| 260 | + let output: TheOpenNetworkSigningOutput = AnySigner.sign(input: input, coin: .ton) | |
| 261 | + guard output.error == .ok, !output.encoded.isEmpty else { | |
| 262 | + throw WalletError.signingFailed | |
| 263 | + } | |
| 264 | + | |
| 265 | + await throttle() | |
| 266 | + var request = URLRequest(url: URL(string: network.v2Base + "/sendBoc")!) | |
| 267 | + request.httpMethod = "POST" | |
| 268 | + request.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
| 269 | + request.httpBody = try JSONSerialization.data(withJSONObject: ["boc": output.encoded]) | |
| 270 | + request.timeoutInterval = 20 | |
| 271 | + let (data, _) = try await URLSession.shared.data(for: request) | |
| 272 | + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any], | |
| 273 | + json["ok"] as? Bool == true else { | |
| 274 | + let message = (try? JSONSerialization.jsonObject(with: data) as? [String: Any])?["error"] as? String | |
| 275 | + throw WalletError.rpc(message ?? "Broadcast failed.") | |
| 276 | + } | |
| 277 | + // toncenter returns the message hash; link the account view instead. | |
| 278 | + let hash = ((json["result"] as? [String: Any])?["hash"] as? String) ?? "" | |
| 279 | + return hash.isEmpty ? address : hash | |
| 280 | + } | |
| 281 | + | |
| 282 | + // MARK: - Formatting | |
| 283 | + | |
| 284 | + public static func formatTON(_ nanotons: UInt64) -> String { | |
| 285 | + TokenAmount.format(BigUInt(nanotons), decimals: tonDecimals, maxFractionDigits: 6) | |
| 286 | + } | |
| 287 | + | |
| 288 | + public static func parseTON(_ input: String) -> UInt64? { | |
| 289 | + guard let units = TokenAmount.parse(input, decimals: tonDecimals), units <= BigUInt(UInt64.max) else { return nil } | |
| 290 | + return UInt64(units) | |
| 291 | + } | |
| 292 | + | |
| 293 | + public static func parseUSDT(_ input: String) -> UInt64? { | |
| 294 | + guard let units = TokenAmount.parse(input, decimals: usdtDecimals), units <= BigUInt(UInt64.max) else { return nil } | |
| 295 | + return UInt64(units) | |
| 296 | + } | |
| 297 | +} | |
added
Sources/OSVaultKit/Services/TransactionService.swift
+221 −0
@@ -0,0 +1,221 @@ | ||
| 1 | +// | |
| 2 | +// TransactionService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | +import Web3Core | |
| 12 | + | |
| 13 | +/// Builds, signs and broadcasts transfers, then tracks the receipt. | |
| 14 | +/// Two shapes: native coin (value transfer) and ERC-20 `transfer` (calldata | |
| 15 | +/// to the token contract). Fee logic follows the chain's FeeModel — the | |
| 16 | +/// research finding is that "EIP-1559" hides four realities (BSC's zero base | |
| 17 | +/// fee, OP-stack/Scroll L1 data fees, Arbitrum's inclusive estimates, Linea's | |
| 18 | +/// pinned base). Gas is ALWAYS estimated, never hardcoded — even for native | |
| 19 | +/// sends (Arbitrum folds L1 costs into the gas limit). | |
| 20 | +public enum TransactionService { | |
| 21 | + | |
| 22 | + public struct PreparedTransfer { | |
| 23 | + public let asset: Asset | |
| 24 | + public let network: Network | |
| 25 | + public let from: String | |
| 26 | + public let recipient: String // checksummed | |
| 27 | + public let amountUnits: BigUInt | |
| 28 | + /// Transaction `to`: the recipient (native) or the token contract (ERC-20). | |
| 29 | + public let txDestination: String | |
| 30 | + public let txValue: BigUInt // amount (native) or 0 (ERC-20) | |
| 31 | + public let calldata: Data | |
| 32 | + public let nonce: BigUInt | |
| 33 | + public let gasLimit: BigUInt | |
| 34 | + public let maxFeePerGas: BigUInt | |
| 35 | + public let maxPriorityFeePerGas: BigUInt | |
| 36 | + /// Rollup L1 data fee (OP-stack/Scroll), deducted silently on-chain — | |
| 37 | + /// shown to the user and included in the balance check. | |
| 38 | + public let l1DataFee: BigUInt | |
| 39 | + | |
| 40 | + /// Worst-case cost in native wei on top of any native amount sent. | |
| 41 | + public var maxGasCostWei: BigUInt { gasLimit * maxFeePerGas + l1DataFee } | |
| 42 | + } | |
| 43 | + | |
| 44 | + // MARK: - Prepare (estimate everything, verify funds) | |
| 45 | + | |
| 46 | + public static func prepare(asset: Asset, | |
| 47 | + network: Network, | |
| 48 | + from: String, | |
| 49 | + recipient: String, | |
| 50 | + amountUnits: BigUInt, | |
| 51 | + rpc: RPCService, | |
| 52 | + balances: Balances) async throws -> PreparedTransfer { | |
| 53 | + guard AddressValidator.validate(recipient) != .invalid else { | |
| 54 | + throw WalletError.invalidAddress | |
| 55 | + } | |
| 56 | + | |
| 57 | + let txDestination: String | |
| 58 | + let txValue: BigUInt | |
| 59 | + let calldata: Data | |
| 60 | + switch asset { | |
| 61 | + case .native: | |
| 62 | + txDestination = recipient | |
| 63 | + txValue = amountUnits | |
| 64 | + calldata = Data() | |
| 65 | + if amountUnits > balances.ethWei { | |
| 66 | + throw WalletError.insufficientTokenBalance | |
| 67 | + } | |
| 68 | + case .token(let token): | |
| 69 | + guard let contract = token.address(on: network) else { | |
| 70 | + throw WalletError.internalError("\(token.symbol) is not deployed on \(network.config.displayName).") | |
| 71 | + } | |
| 72 | + guard let data = Hex.erc20TransferData(to: recipient, amount: amountUnits) else { | |
| 73 | + throw WalletError.invalidAddress | |
| 74 | + } | |
| 75 | + txDestination = contract | |
| 76 | + txValue = 0 | |
| 77 | + calldata = data | |
| 78 | + if let held = balances.tokenUnits[token.symbol], amountUnits > held { | |
| 79 | + throw WalletError.insufficientTokenBalance | |
| 80 | + } | |
| 81 | + } | |
| 82 | + | |
| 83 | + let nonce = try await rpc.transactionCount(of: from) | |
| 84 | + let fees = try await feeParameters(for: network, rpc: rpc) | |
| 85 | + | |
| 86 | + let estimated = try await rpc.estimateGas( | |
| 87 | + from: from, to: txDestination, valueWei: txValue, data: calldata | |
| 88 | + ) | |
| 89 | + // Headroom on the estimate — except Arbitrum, whose estimate already | |
| 90 | + // embeds the L1 buffer and is meant to be used verbatim. | |
| 91 | + let gasLimit = network.config.feeModel == .arbitrumInclusive | |
| 92 | + ? estimated | |
| 93 | + : estimated * 12 / 10 | |
| 94 | + | |
| 95 | + // L1 data fee via the rollup's oracle, on an unsigned serialization | |
| 96 | + // of the tx. Best effort: a failing oracle call must not block sends. | |
| 97 | + var l1Fee: BigUInt = 0 | |
| 98 | + if let oracle = network.l1FeeOracle, | |
| 99 | + let destination = EthereumAddress(txDestination, ignoreChecksum: true) { | |
| 100 | + var draft = CodableTransaction( | |
| 101 | + type: .eip1559, to: destination, nonce: nonce, | |
| 102 | + chainID: network.config.chainID, value: txValue, data: calldata, | |
| 103 | + gasLimit: gasLimit, maxFeePerGas: fees.maxFee, maxPriorityFeePerGas: fees.tip | |
| 104 | + ) | |
| 105 | + if let serialized = draft.encode(for: .signature) { | |
| 106 | + var call = Data([0x49, 0x94, 0x8e, 0x0e]) // getL1Fee(bytes) | |
| 107 | + call.append(Hex.abiWord(BigUInt(32))) // offset | |
| 108 | + call.append(Hex.abiWord(BigUInt(serialized.count))) // length | |
| 109 | + var padded = serialized | |
| 110 | + if padded.count % 32 != 0 { | |
| 111 | + padded.append(Data(repeating: 0, count: 32 - padded.count % 32)) | |
| 112 | + } | |
| 113 | + call.append(padded) | |
| 114 | + if let result = try? await rpc.call(to: oracle, data: call), | |
| 115 | + let fee = Hex.toBigUInt(result) { | |
| 116 | + l1Fee = fee | |
| 117 | + } | |
| 118 | + } | |
| 119 | + } | |
| 120 | + | |
| 121 | + let prepared = PreparedTransfer( | |
| 122 | + asset: asset, network: network, from: from, recipient: recipient, | |
| 123 | + amountUnits: amountUnits, txDestination: txDestination, | |
| 124 | + txValue: txValue, calldata: calldata, | |
| 125 | + nonce: nonce, gasLimit: gasLimit, | |
| 126 | + maxFeePerGas: fees.maxFee, maxPriorityFeePerGas: fees.tip, | |
| 127 | + l1DataFee: l1Fee | |
| 128 | + ) | |
| 129 | + | |
| 130 | + // Native sends must cover amount + gas; token sends just the gas. | |
| 131 | + let required = txValue + prepared.maxGasCostWei | |
| 132 | + if balances.ethWei < required { | |
| 133 | + throw WalletError.insufficientETHForGas( | |
| 134 | + needWei: TokenAmount.formatWei(required), | |
| 135 | + haveWei: TokenAmount.formatWei(balances.ethWei) | |
| 136 | + ) | |
| 137 | + } | |
| 138 | + return prepared | |
| 139 | + } | |
| 140 | + | |
| 141 | + /// Per-FeeModel (maxFeePerGas, maxPriorityFeePerGas). | |
| 142 | + static func feeParameters(for network: Network, | |
| 143 | + rpc: RPCService) async throws -> (maxFee: BigUInt, tip: BigUInt) { | |
| 144 | + switch network.config.feeModel { | |
| 145 | + case .zeroBaseFee: | |
| 146 | + // BSC: baseFee is 0 (BEP-226); price entirely via gasPrice. | |
| 147 | + let gasPrice = try await rpc.gasPrice() | |
| 148 | + return (max(gasPrice, 1), max(gasPrice, 1)) | |
| 149 | + case .lineaPinnedBase: | |
| 150 | + // Base fee pinned at 7 wei; the tip is the real price. | |
| 151 | + let gasPrice = try await rpc.gasPrice() | |
| 152 | + let tip = (try? await rpc.maxPriorityFeePerGas()) ?? gasPrice | |
| 153 | + return (max(gasPrice * 12 / 10, tip + 7), max(tip, 1)) | |
| 154 | + case .arbitrumInclusive: | |
| 155 | + // Suggested tip is 0; cost = gasLimit × (2×base). | |
| 156 | + let baseFee = try await rpc.latestBaseFee() | |
| 157 | + let tip = (try? await rpc.maxPriorityFeePerGas()) ?? 0 | |
| 158 | + return (baseFee * 2 + tip, tip) | |
| 159 | + case .eip1559, .opStackL1Fee, .scrollL1Fee: | |
| 160 | + let baseFee = try await rpc.latestBaseFee() | |
| 161 | + let tip: BigUInt | |
| 162 | + if let suggested = try? await rpc.maxPriorityFeePerGas() { | |
| 163 | + tip = max(suggested, 1) | |
| 164 | + } else { | |
| 165 | + tip = 1_000_000 // 0.001 gwei — plenty on modern L2s | |
| 166 | + } | |
| 167 | + return (baseFee * 2 + tip, tip) | |
| 168 | + } | |
| 169 | + } | |
| 170 | + | |
| 171 | + // MARK: - Sign + broadcast | |
| 172 | + | |
| 173 | + public static func send(_ prepared: PreparedTransfer, privateKey: Data, rpc: RPCService) async throws -> String { | |
| 174 | + guard let destination = EthereumAddress(prepared.txDestination, ignoreChecksum: true) else { | |
| 175 | + throw WalletError.internalError("Bad destination address.") | |
| 176 | + } | |
| 177 | + var tx = CodableTransaction( | |
| 178 | + type: .eip1559, | |
| 179 | + to: destination, | |
| 180 | + nonce: prepared.nonce, | |
| 181 | + chainID: prepared.network.config.chainID, | |
| 182 | + value: prepared.txValue, | |
| 183 | + data: prepared.calldata, | |
| 184 | + gasLimit: prepared.gasLimit, | |
| 185 | + maxFeePerGas: prepared.maxFeePerGas, | |
| 186 | + maxPriorityFeePerGas: prepared.maxPriorityFeePerGas | |
| 187 | + ) | |
| 188 | + do { | |
| 189 | + try tx.sign(privateKey: privateKey) | |
| 190 | + } catch { | |
| 191 | + throw WalletError.signingFailed | |
| 192 | + } | |
| 193 | + guard let raw = tx.encode(for: .transaction) else { | |
| 194 | + throw WalletError.signingFailed | |
| 195 | + } | |
| 196 | + return try await rpc.sendRawTransaction(Hex.string(raw)) | |
| 197 | + } | |
| 198 | + | |
| 199 | + // MARK: - Receipt tracking | |
| 200 | + | |
| 201 | + public enum Confirmation { | |
| 202 | + case confirmed | |
| 203 | + case failed | |
| 204 | + case timedOut | |
| 205 | + } | |
| 206 | + | |
| 207 | + public static func waitForReceipt(hash: String, | |
| 208 | + rpc: RPCService, | |
| 209 | + pollEvery seconds: Double = 3, | |
| 210 | + timeout: Double = 300) async -> Confirmation { | |
| 211 | + let deadline = Date().addingTimeInterval(timeout) | |
| 212 | + while Date() < deadline { | |
| 213 | + if let receipt = try? await rpc.transactionReceipt(hash) { | |
| 214 | + return receipt.succeeded ? .confirmed : .failed | |
| 215 | + } | |
| 216 | + try? await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000)) | |
| 217 | + if Task.isCancelled { return .timedOut } | |
| 218 | + } | |
| 219 | + return .timedOut | |
| 220 | + } | |
| 221 | +} | |
added
Sources/OSVaultKit/Services/TronService.swift
+323 −0
@@ -0,0 +1,323 @@ | ||
| 1 | +// | |
| 2 | +// TronService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | +import WalletCore | |
| 12 | +import Web3Core | |
| 13 | + | |
| 14 | +/// Tron support — the largest USDT corridor. Signing via the vendored Trust | |
| 15 | +/// wallet-core (`TransferContract` / `TransferTRC20Contract`), networking via | |
| 16 | +/// keyless TronGrid REST with polite backoff (research: anonymous rate is | |
| 17 | +/// throttled but ample for one wallet). | |
| 18 | +/// | |
| 19 | +/// The Tron trap is the fee model: TRC-20 transfers consume ~65k energy | |
| 20 | +/// (~130k to a fresh recipient); without staked energy the network burns | |
| 21 | +/// ~13–27 TRX. The estimate is computed pre-send via | |
| 22 | +/// `triggerconstantcontract` and shown to the user; `fee_limit` caps the burn. | |
| 23 | +/// | |
| 24 | +/// Same security model: only the base58 address stays in memory; sends | |
| 25 | +/// re-derive the key from the vault password and discard it. | |
| 26 | +public actor TronService { | |
| 27 | + | |
| 28 | + public enum TronNetwork: String, CaseIterable, Codable, Sendable { | |
| 29 | + case mainnet | |
| 30 | + case nile // testnet, faucet at nileex.io | |
| 31 | + | |
| 32 | + public var apiBase: String { | |
| 33 | + switch self { | |
| 34 | + case .mainnet: return "https://api.trongrid.io" | |
| 35 | + case .nile: return "https://nile.trongrid.io" | |
| 36 | + } | |
| 37 | + } | |
| 38 | + | |
| 39 | + /// USDT TRC-20 (verified live via symbol()/decimals(), 6 decimals). | |
| 40 | + public var usdtContract: String { | |
| 41 | + switch self { | |
| 42 | + case .mainnet: return "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" | |
| 43 | + case .nile: return "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf" | |
| 44 | + } | |
| 45 | + } | |
| 46 | + | |
| 47 | + public func explorerTxURL(_ txid: String) -> URL { | |
| 48 | + switch self { | |
| 49 | + case .mainnet: return URL(string: "https://tronscan.org/#/transaction/\(txid)")! | |
| 50 | + case .nile: return URL(string: "https://nile.tronscan.org/#/transaction/\(txid)")! | |
| 51 | + } | |
| 52 | + } | |
| 53 | + | |
| 54 | + public func explorerAddressURL(_ address: String) -> URL { | |
| 55 | + switch self { | |
| 56 | + case .mainnet: return URL(string: "https://tronscan.org/#/address/\(address)")! | |
| 57 | + case .nile: return URL(string: "https://nile.tronscan.org/#/address/\(address)")! | |
| 58 | + } | |
| 59 | + } | |
| 60 | + | |
| 61 | + public var displayName: String { | |
| 62 | + switch self { | |
| 63 | + case .mainnet: return "Tron" | |
| 64 | + case .nile: return "Tron Nile" | |
| 65 | + } | |
| 66 | + } | |
| 67 | + | |
| 68 | + public var isTestnet: Bool { self == .nile } | |
| 69 | + } | |
| 70 | + | |
| 71 | + public static let networkKey = "osvault.tron.network" | |
| 72 | + public static let usdtDecimals = 6 | |
| 73 | + public static let trxDecimals = 6 // 1 TRX = 1_000_000 sun | |
| 74 | + static let energyPriceSun: UInt64 = 420 // current chain parameter | |
| 75 | + static let feeLimitSun: Int64 = 100_000_000 // 100 TRX ceiling | |
| 76 | + | |
| 77 | + public struct TronBalances: Sendable { | |
| 78 | + public var trxSun: UInt64 = 0 | |
| 79 | + public var usdtUnits: UInt64 = 0 | |
| 80 | + } | |
| 81 | + | |
| 82 | + public struct PreparedTronSend: Sendable { | |
| 83 | + public let recipient: String | |
| 84 | + public let amountUnits: UInt64 | |
| 85 | + public let isUSDT: Bool | |
| 86 | + /// Estimated burn in sun if no staked energy/bandwidth covers it. | |
| 87 | + public let estimatedFeeSun: UInt64 | |
| 88 | + public let network: TronNetwork | |
| 89 | + } | |
| 90 | + | |
| 91 | + private var address: String? | |
| 92 | + private var network: TronNetwork = .nile | |
| 93 | + | |
| 94 | + // MARK: - Setup | |
| 95 | + | |
| 96 | + public func configure(mnemonic: String) throws { | |
| 97 | + let stored = UserDefaults.standard.string(forKey: Self.networkKey) | |
| 98 | + network = stored.flatMap(TronNetwork.init(rawValue:)) ?? .nile | |
| 99 | + guard let wallet = HDWallet(mnemonic: mnemonic, passphrase: "") else { | |
| 100 | + throw WalletError.invalidMnemonic | |
| 101 | + } | |
| 102 | + address = wallet.getAddressForCoin(coin: .tron) | |
| 103 | + } | |
| 104 | + | |
| 105 | + public var isConfigured: Bool { address != nil } | |
| 106 | + public var currentNetwork: TronNetwork { network } | |
| 107 | + public var publicAddress: String? { address } | |
| 108 | + | |
| 109 | + /// Address is network-independent; no password needed. | |
| 110 | + public func switchNetwork(to newNetwork: TronNetwork) { | |
| 111 | + UserDefaults.standard.set(newNetwork.rawValue, forKey: Self.networkKey) | |
| 112 | + network = newNetwork | |
| 113 | + } | |
| 114 | + | |
| 115 | + public static func validate(address: String) -> Bool { | |
| 116 | + AnyAddress.isValid(string: address, coin: .tron) | |
| 117 | + } | |
| 118 | + | |
| 119 | + // MARK: - HTTP | |
| 120 | + | |
| 121 | + private func post(_ path: String, body: [String: Any]) async throws -> [String: Any] { | |
| 122 | + var request = URLRequest(url: URL(string: network.apiBase + path)!) | |
| 123 | + request.httpMethod = "POST" | |
| 124 | + request.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
| 125 | + request.httpBody = try JSONSerialization.data(withJSONObject: body) | |
| 126 | + request.timeoutInterval = 20 | |
| 127 | + var lastError: Error = WalletError.rpc("TronGrid unreachable.") | |
| 128 | + for attempt in 0..<3 { | |
| 129 | + if attempt > 0 { | |
| 130 | + try? await Task.sleep(nanoseconds: UInt64(attempt) * 1_200_000_000) | |
| 131 | + } | |
| 132 | + do { | |
| 133 | + let (data, response) = try await URLSession.shared.data(for: request) | |
| 134 | + if let http = response as? HTTPURLResponse, http.statusCode == 403 { | |
| 135 | + lastError = WalletError.rpc("TronGrid rate limit — retrying.") | |
| 136 | + continue | |
| 137 | + } | |
| 138 | + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { | |
| 139 | + lastError = WalletError.rpc("Malformed TronGrid response.") | |
| 140 | + continue | |
| 141 | + } | |
| 142 | + return json | |
| 143 | + } catch { | |
| 144 | + lastError = WalletError.rpc(error.localizedDescription) | |
| 145 | + } | |
| 146 | + } | |
| 147 | + throw lastError | |
| 148 | + } | |
| 149 | + | |
| 150 | + private func get(_ path: String) async throws -> [String: Any] { | |
| 151 | + var request = URLRequest(url: URL(string: network.apiBase + path)!) | |
| 152 | + request.timeoutInterval = 20 | |
| 153 | + let (data, _) = try await URLSession.shared.data(for: request) | |
| 154 | + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { | |
| 155 | + throw WalletError.rpc("Malformed TronGrid response.") | |
| 156 | + } | |
| 157 | + return json | |
| 158 | + } | |
| 159 | + | |
| 160 | + // MARK: - Balances | |
| 161 | + | |
| 162 | + public func fetchBalances() async throws -> TronBalances { | |
| 163 | + guard let address else { throw WalletError.internalError("Tron not configured.") } | |
| 164 | + var balances = TronBalances() | |
| 165 | + let json = try await get("/v1/accounts/\(address)") | |
| 166 | + guard let accounts = json["data"] as? [[String: Any]] else { | |
| 167 | + throw WalletError.rpc("TronGrid account query failed.") | |
| 168 | + } | |
| 169 | + guard let account = accounts.first else { | |
| 170 | + return balances // unactivated account: all zero | |
| 171 | + } | |
| 172 | + if let sun = account["balance"] as? NSNumber { | |
| 173 | + balances.trxSun = sun.uint64Value | |
| 174 | + } | |
| 175 | + if let trc20 = account["trc20"] as? [[String: String]] { | |
| 176 | + for entry in trc20 { | |
| 177 | + if let value = entry[network.usdtContract], let units = UInt64(value) { | |
| 178 | + balances.usdtUnits = units | |
| 179 | + } | |
| 180 | + } | |
| 181 | + } | |
| 182 | + return balances | |
| 183 | + } | |
| 184 | + | |
| 185 | + // MARK: - Estimate | |
| 186 | + | |
| 187 | + public func estimateSend(to recipient: String, amountUnits: UInt64, isUSDT: Bool) async throws -> PreparedTronSend { | |
| 188 | + guard let address else { throw WalletError.internalError("Tron not configured.") } | |
| 189 | + guard Self.validate(address: recipient) else { throw WalletError.invalidAddress } | |
| 190 | + | |
| 191 | + var feeSun: UInt64 = 0 | |
| 192 | + if isUSDT { | |
| 193 | + // ABI-encode transfer(address,uint256): hex address (21 bytes, | |
| 194 | + // 0x41-prefixed) left-padded + amount. | |
| 195 | + guard let recipientHex = TronService.base58ToHex(recipient) else { | |
| 196 | + throw WalletError.invalidAddress | |
| 197 | + } | |
| 198 | + let param = String(repeating: "0", count: 24) + recipientHex.dropFirst(2) // strip 0x41 prefix byte | |
| 199 | + + String(String(repeating: "0", count: 64 - String(amountUnits, radix: 16).count) | |
| 200 | + + String(amountUnits, radix: 16)) | |
| 201 | + let json = try await post("/wallet/triggerconstantcontract", body: [ | |
| 202 | + "owner_address": address, | |
| 203 | + "contract_address": network.usdtContract, | |
| 204 | + "function_selector": "transfer(address,uint256)", | |
| 205 | + "parameter": param, | |
| 206 | + "visible": true | |
| 207 | + ]) | |
| 208 | + let energy = (json["energy_used"] as? NSNumber)?.uint64Value ?? 130_000 | |
| 209 | + feeSun = energy * Self.energyPriceSun + 350_000 // + bandwidth burn margin | |
| 210 | + } else { | |
| 211 | + // Plain TRX transfer: bandwidth only (~270 bytes), plus 1 TRX | |
| 212 | + // account-creation fee if the recipient is fresh. | |
| 213 | + let account = try await post("/wallet/getaccount", body: ["address": recipient, "visible": true]) | |
| 214 | + let isFresh = account.isEmpty || account["address"] == nil | |
| 215 | + feeSun = (isFresh ? 1_100_000 : 300_000) | |
| 216 | + } | |
| 217 | + | |
| 218 | + return PreparedTronSend( | |
| 219 | + recipient: recipient, amountUnits: amountUnits, | |
| 220 | + isUSDT: isUSDT, estimatedFeeSun: feeSun, network: network | |
| 221 | + ) | |
| 222 | + } | |
| 223 | + | |
| 224 | + // MARK: - Sign + broadcast (wallet-core) | |
| 225 | + | |
| 226 | + public func send(_ prepared: PreparedTronSend, mnemonic: String) async throws -> String { | |
| 227 | + guard let address else { throw WalletError.internalError("Tron not configured.") } | |
| 228 | + guard let wallet = HDWallet(mnemonic: mnemonic, passphrase: "") else { | |
| 229 | + throw WalletError.invalidMnemonic | |
| 230 | + } | |
| 231 | + let key = wallet.getKeyForCoin(coin: .tron) | |
| 232 | + | |
| 233 | + // Reference block for the tx header. | |
| 234 | + let now = try await post("/wallet/getnowblock", body: [:]) | |
| 235 | + guard let header = (now["block_header"] as? [String: Any])?["raw_data"] as? [String: Any], | |
| 236 | + let number = (header["number"] as? NSNumber)?.int64Value, | |
| 237 | + let version = (header["version"] as? NSNumber)?.int32Value, | |
| 238 | + let timestamp = (header["timestamp"] as? NSNumber)?.int64Value, | |
| 239 | + let txTrieRoot = header["txTrieRoot"] as? String, | |
| 240 | + let parentHash = header["parentHash"] as? String, | |
| 241 | + let witness = header["witness_address"] as? String, | |
| 242 | + let blockID = now["blockID"] as? String else { | |
| 243 | + throw WalletError.rpc("Could not fetch the reference block.") | |
| 244 | + } | |
| 245 | + _ = blockID | |
| 246 | + | |
| 247 | + var block = TronBlockHeader() | |
| 248 | + block.number = number | |
| 249 | + block.version = version | |
| 250 | + block.timestamp = timestamp | |
| 251 | + block.txTrieRoot = Hex.data(txTrieRoot) ?? Data() | |
| 252 | + block.parentHash = Hex.data(parentHash) ?? Data() | |
| 253 | + block.witnessAddress = Hex.data(witness) ?? Data() | |
| 254 | + | |
| 255 | + var tx = TronTransaction() | |
| 256 | + tx.timestamp = timestamp | |
| 257 | + tx.expiration = timestamp + 10 * 60 * 1000 // 10 minutes | |
| 258 | + tx.blockHeader = block | |
| 259 | + if prepared.isUSDT { | |
| 260 | + tx.feeLimit = Self.feeLimitSun | |
| 261 | + var contract = TronTransferTRC20Contract() | |
| 262 | + contract.ownerAddress = address | |
| 263 | + contract.contractAddress = prepared.network.usdtContract | |
| 264 | + contract.toAddress = prepared.recipient | |
| 265 | + contract.amount = Hex.abiWord(BigUInt(prepared.amountUnits)) | |
| 266 | + tx.contractOneof = .transferTrc20Contract(contract) | |
| 267 | + } else { | |
| 268 | + var contract = TronTransferContract() | |
| 269 | + contract.ownerAddress = address | |
| 270 | + contract.toAddress = prepared.recipient | |
| 271 | + contract.amount = Int64(prepared.amountUnits) | |
| 272 | + tx.contractOneof = .transfer(contract) | |
| 273 | + } | |
| 274 | + | |
| 275 | + var input = TronSigningInput() | |
| 276 | + input.transaction = tx | |
| 277 | + input.privateKey = key.data | |
| 278 | + let output: TronSigningOutput = AnySigner.sign(input: input, coin: .tron) | |
| 279 | + guard output.error == .ok, !output.json.isEmpty else { | |
| 280 | + throw WalletError.signingFailed | |
| 281 | + } | |
| 282 | + | |
| 283 | + // Broadcast the signed JSON exactly as wallet-core produced it. | |
| 284 | + var request = URLRequest(url: URL(string: network.apiBase + "/wallet/broadcasttransaction")!) | |
| 285 | + request.httpMethod = "POST" | |
| 286 | + request.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
| 287 | + request.httpBody = output.json.data(using: .utf8) | |
| 288 | + request.timeoutInterval = 20 | |
| 289 | + let (data, _) = try await URLSession.shared.data(for: request) | |
| 290 | + guard let result = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { | |
| 291 | + throw WalletError.rpc("Broadcast failed.") | |
| 292 | + } | |
| 293 | + if let ok = result["result"] as? Bool, ok { | |
| 294 | + return output.id.map { String(format: "%02x", $0) }.joined() | |
| 295 | + } | |
| 296 | + let message = (result["message"] as? String).flatMap { | |
| 297 | + Data(base64Encoded: $0).flatMap { String(data: $0, encoding: .utf8) } | |
| 298 | + } ?? (result["code"] as? String ?? "Broadcast rejected.") | |
| 299 | + throw WalletError.rpc(message) | |
| 300 | + } | |
| 301 | + | |
| 302 | + // MARK: - Helpers | |
| 303 | + | |
| 304 | + /// Base58check T-address → 0x41-prefixed hex (21 bytes, lowercase, no 0x). | |
| 305 | + static func base58ToHex(_ address: String) -> String? { | |
| 306 | + guard let decoded = Base58.decode(string: address), decoded.count == 21 else { return nil } | |
| 307 | + return decoded.map { String(format: "%02x", $0) }.joined() | |
| 308 | + } | |
| 309 | + | |
| 310 | + public static func formatTRX(_ sun: UInt64) -> String { | |
| 311 | + TokenAmount.format(BigUInt(sun), decimals: trxDecimals) | |
| 312 | + } | |
| 313 | + | |
| 314 | + public static func parseTRX(_ input: String) -> UInt64? { | |
| 315 | + guard let units = TokenAmount.parse(input, decimals: trxDecimals), units <= BigUInt(UInt64.max) else { return nil } | |
| 316 | + return UInt64(units) | |
| 317 | + } | |
| 318 | + | |
| 319 | + public static func parseUSDT(_ input: String) -> UInt64? { | |
| 320 | + guard let units = TokenAmount.parse(input, decimals: usdtDecimals), units <= BigUInt(UInt64.max) else { return nil } | |
| 321 | + return UInt64(units) | |
| 322 | + } | |
| 323 | +} | |
added
Sources/OSVaultKit/Services/VaultCrypto.swift
+96 −0
@@ -0,0 +1,96 @@ | ||
| 1 | +// | |
| 2 | +// VaultCrypto.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import CryptoKit | |
| 11 | +import CommonCrypto | |
| 12 | + | |
| 13 | +/// OS Vault's own encryption mechanism — deliberately independent of the | |
| 14 | +/// macOS Keychain. The secret (mnemonic) is sealed into a portable JSON file: | |
| 15 | +/// | |
| 16 | +/// password ── PBKDF2-HMAC-SHA512 (600k rounds, random 32-byte salt) ──▶ 256-bit key | |
| 17 | +/// secret ──── AES-256-GCM (random nonce, tag authenticates the file) ──▶ ciphertext | |
| 18 | +/// | |
| 19 | +/// A wrong password or a tampered file both fail GCM authentication; the two | |
| 20 | +/// cases are indistinguishable by design. | |
| 21 | +public enum VaultCrypto { | |
| 22 | + | |
| 23 | + public static let currentVersion = 1 | |
| 24 | + public static let defaultIterations = 600_000 | |
| 25 | + | |
| 26 | + public struct VaultFile: Codable, Equatable { | |
| 27 | + public struct KDF: Codable, Equatable { | |
| 28 | + public let algorithm: String // "pbkdf2-hmac-sha512" | |
| 29 | + public let iterations: Int | |
| 30 | + public let salt: String // base64 | |
| 31 | + } | |
| 32 | + public let version: Int | |
| 33 | + public let kdf: KDF | |
| 34 | + public let cipher: String // "aes-256-gcm" | |
| 35 | + public let ciphertext: String // base64, GCM combined (nonce ‖ ct ‖ tag) | |
| 36 | + } | |
| 37 | + | |
| 38 | + public static func seal(secret: Data, password: String, | |
| 39 | + iterations: Int = defaultIterations) throws -> VaultFile { | |
| 40 | + var salt = Data(count: 32) | |
| 41 | + let saltStatus = salt.withUnsafeMutableBytes { ptr in | |
| 42 | + SecRandomCopyBytes(kSecRandomDefault, 32, ptr.baseAddress!) | |
| 43 | + } | |
| 44 | + guard saltStatus == errSecSuccess else { throw WalletError.internalError("Entropy source unavailable.") } | |
| 45 | + | |
| 46 | + let key = try deriveKey(password: password, salt: salt, iterations: iterations) | |
| 47 | + let sealed = try AES.GCM.seal(secret, using: key) | |
| 48 | + guard let combined = sealed.combined else { throw WalletError.internalError("Encryption failed.") } | |
| 49 | + | |
| 50 | + return VaultFile( | |
| 51 | + version: currentVersion, | |
| 52 | + kdf: .init(algorithm: "pbkdf2-hmac-sha512", iterations: iterations, salt: salt.base64EncodedString()), | |
| 53 | + cipher: "aes-256-gcm", | |
| 54 | + ciphertext: combined.base64EncodedString() | |
| 55 | + ) | |
| 56 | + } | |
| 57 | + | |
| 58 | + public static func open(_ vault: VaultFile, password: String) throws -> Data { | |
| 59 | + guard vault.version == currentVersion, | |
| 60 | + vault.kdf.algorithm == "pbkdf2-hmac-sha512", | |
| 61 | + vault.cipher == "aes-256-gcm", | |
| 62 | + let salt = Data(base64Encoded: vault.kdf.salt), | |
| 63 | + let combined = Data(base64Encoded: vault.ciphertext), | |
| 64 | + vault.kdf.iterations >= 10_000 else { | |
| 65 | + throw WalletError.vaultCorrupted | |
| 66 | + } | |
| 67 | + let key = try deriveKey(password: password, salt: salt, iterations: vault.kdf.iterations) | |
| 68 | + do { | |
| 69 | + let box = try AES.GCM.SealedBox(combined: combined) | |
| 70 | + return try AES.GCM.open(box, using: key) | |
| 71 | + } catch { | |
| 72 | + throw WalletError.wrongPassword | |
| 73 | + } | |
| 74 | + } | |
| 75 | + | |
| 76 | + static func deriveKey(password: String, salt: Data, iterations: Int) throws -> SymmetricKey { | |
| 77 | + let passwordData = Data(password.utf8) | |
| 78 | + var derived = Data(count: 32) | |
| 79 | + let status = derived.withUnsafeMutableBytes { derivedPtr in | |
| 80 | + salt.withUnsafeBytes { saltPtr in | |
| 81 | + passwordData.withUnsafeBytes { passPtr in | |
| 82 | + CCKeyDerivationPBKDF( | |
| 83 | + CCPBKDFAlgorithm(kCCPBKDF2), | |
| 84 | + passPtr.bindMemory(to: Int8.self).baseAddress, passwordData.count, | |
| 85 | + saltPtr.bindMemory(to: UInt8.self).baseAddress, salt.count, | |
| 86 | + CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA512), | |
| 87 | + UInt32(iterations), | |
| 88 | + derivedPtr.bindMemory(to: UInt8.self).baseAddress, 32 | |
| 89 | + ) | |
| 90 | + } | |
| 91 | + } | |
| 92 | + } | |
| 93 | + guard status == kCCSuccess else { throw WalletError.internalError("Key derivation failed.") } | |
| 94 | + return SymmetricKey(data: derived) | |
| 95 | + } | |
| 96 | +} | |
added
Sources/OSVaultKit/Services/XRPLService.swift
+326 −0
@@ -0,0 +1,326 @@ | ||
| 1 | +// | |
| 2 | +// XRPLService.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | +import WalletCore | |
| 12 | + | |
| 13 | +/// XRP Ledger support: XRP + RLUSD (Ripple's stablecoin, an issued currency). | |
| 14 | +/// Signing via wallet-core (`OperationPayment` / `OperationTrustSet`), | |
| 15 | +/// networking via the genuinely free public JSON-RPC servers (xrplcluster.com | |
| 16 | +/// community full-history cluster; s.altnet.rippletest.net for testnet). | |
| 17 | +/// | |
| 18 | +/// XRPL specifics surfaced to the user: the 1 XRP base reserve (+0.2 XRP per | |
| 19 | +/// trustline) is locked, not spendable; RLUSD requires a trustline — the app | |
| 20 | +/// offers one-tap creation and blocks sends to recipients without one. | |
| 21 | +public actor XRPLService { | |
| 22 | + | |
| 23 | + public enum XRPLNetwork: String, CaseIterable, Codable, Sendable { | |
| 24 | + case mainnet | |
| 25 | + case testnet | |
| 26 | + | |
| 27 | + public var apiURL: String { | |
| 28 | + switch self { | |
| 29 | + case .mainnet: return "https://xrplcluster.com" | |
| 30 | + case .testnet: return "https://s.altnet.rippletest.net:51234" | |
| 31 | + } | |
| 32 | + } | |
| 33 | + | |
| 34 | + var fallbackURL: String? { | |
| 35 | + switch self { | |
| 36 | + case .mainnet: return "https://s1.ripple.com:51234" | |
| 37 | + case .testnet: return nil | |
| 38 | + } | |
| 39 | + } | |
| 40 | + | |
| 41 | + /// RLUSD issuer (mainnet from Ripple docs; testnet issuer verified | |
| 42 | + /// live via account_info — tryrlusd.com faucet). | |
| 43 | + public var rlusdIssuer: String { | |
| 44 | + switch self { | |
| 45 | + case .mainnet: return "rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De" | |
| 46 | + case .testnet: return "rQhWct2fv4Vc4KRjRgMrxa8xPN9Zx9iLKV" | |
| 47 | + } | |
| 48 | + } | |
| 49 | + | |
| 50 | + public func explorerTxURL(_ hash: String) -> URL { | |
| 51 | + switch self { | |
| 52 | + case .mainnet: return URL(string: "https://livenet.xrpl.org/transactions/\(hash)")! | |
| 53 | + case .testnet: return URL(string: "https://testnet.xrpl.org/transactions/\(hash)")! | |
| 54 | + } | |
| 55 | + } | |
| 56 | + | |
| 57 | + public func explorerAddressURL(_ address: String) -> URL { | |
| 58 | + switch self { | |
| 59 | + case .mainnet: return URL(string: "https://livenet.xrpl.org/accounts/\(address)")! | |
| 60 | + case .testnet: return URL(string: "https://testnet.xrpl.org/accounts/\(address)")! | |
| 61 | + } | |
| 62 | + } | |
| 63 | + | |
| 64 | + public var displayName: String { | |
| 65 | + switch self { | |
| 66 | + case .mainnet: return "XRP Ledger" | |
| 67 | + case .testnet: return "XRPL Testnet" | |
| 68 | + } | |
| 69 | + } | |
| 70 | + | |
| 71 | + public var isTestnet: Bool { self == .testnet } | |
| 72 | + } | |
| 73 | + | |
| 74 | + public static let networkKey = "osvault.xrpl.network" | |
| 75 | + /// 160-bit hex currency code for "RLUSD" (non-standard >3-char code). | |
| 76 | + public static let rlusdCurrencyHex = "524C555344000000000000000000000000000000" | |
| 77 | + public static let xrpDecimals = 6 // 1 XRP = 1_000_000 drops | |
| 78 | + static let baseReserveDrops: UInt64 = 1_000_000 | |
| 79 | + static let ownerReserveDrops: UInt64 = 200_000 | |
| 80 | + | |
| 81 | + public struct XRPLBalances: Sendable { | |
| 82 | + public var drops: UInt64 = 0 | |
| 83 | + public var reserveDrops: UInt64 = 0 | |
| 84 | + public var rlusdValue: String = "0" // issued-currency decimal string | |
| 85 | + public var hasRLUSDTrustline = false | |
| 86 | + public var accountExists = false | |
| 87 | + public var spendableDrops: UInt64 { | |
| 88 | + drops > reserveDrops ? drops - reserveDrops : 0 | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 92 | + public struct PreparedXRPLSend: Sendable { | |
| 93 | + public let recipient: String | |
| 94 | + /// Drops for XRP; decimal string for RLUSD. | |
| 95 | + public let amountDrops: UInt64 | |
| 96 | + public let amountValue: String | |
| 97 | + public let isRLUSD: Bool | |
| 98 | + public let feeDrops: UInt64 | |
| 99 | + public let activatesRecipient: Bool | |
| 100 | + public let network: XRPLNetwork | |
| 101 | + } | |
| 102 | + | |
| 103 | + private var address: String? | |
| 104 | + private var network: XRPLNetwork = .testnet | |
| 105 | + | |
| 106 | + // MARK: - Setup | |
| 107 | + | |
| 108 | + public func configure(mnemonic: String) throws { | |
| 109 | + let stored = UserDefaults.standard.string(forKey: Self.networkKey) | |
| 110 | + network = stored.flatMap(XRPLNetwork.init(rawValue:)) ?? .testnet | |
| 111 | + guard let wallet = HDWallet(mnemonic: mnemonic, passphrase: "") else { | |
| 112 | + throw WalletError.invalidMnemonic | |
| 113 | + } | |
| 114 | + address = wallet.getAddressForCoin(coin: .xrp) | |
| 115 | + } | |
| 116 | + | |
| 117 | + public var isConfigured: Bool { address != nil } | |
| 118 | + public var currentNetwork: XRPLNetwork { network } | |
| 119 | + public var publicAddress: String? { address } | |
| 120 | + | |
| 121 | + public func switchNetwork(to newNetwork: XRPLNetwork) { | |
| 122 | + UserDefaults.standard.set(newNetwork.rawValue, forKey: Self.networkKey) | |
| 123 | + network = newNetwork | |
| 124 | + } | |
| 125 | + | |
| 126 | + public static func validate(address: String) -> Bool { | |
| 127 | + AnyAddress.isValid(string: address, coin: .xrp) | |
| 128 | + } | |
| 129 | + | |
| 130 | + // MARK: - JSON-RPC | |
| 131 | + | |
| 132 | + private func rpc(_ method: String, _ params: [String: Any]) async throws -> [String: Any] { | |
| 133 | + let body: [String: Any] = ["method": method, "params": [params]] | |
| 134 | + var lastError: Error = WalletError.rpc("XRPL endpoint unreachable.") | |
| 135 | + for url in [network.apiURL, network.fallbackURL].compactMap({ $0 }) { | |
| 136 | + var request = URLRequest(url: URL(string: url)!) | |
| 137 | + request.httpMethod = "POST" | |
| 138 | + request.setValue("application/json", forHTTPHeaderField: "Content-Type") | |
| 139 | + request.httpBody = try JSONSerialization.data(withJSONObject: body) | |
| 140 | + request.timeoutInterval = 20 | |
| 141 | + do { | |
| 142 | + let (data, _) = try await URLSession.shared.data(for: request) | |
| 143 | + guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any], | |
| 144 | + let result = json["result"] as? [String: Any] else { | |
| 145 | + lastError = WalletError.rpc("Malformed XRPL response.") | |
| 146 | + continue | |
| 147 | + } | |
| 148 | + return result | |
| 149 | + } catch { | |
| 150 | + lastError = WalletError.rpc(error.localizedDescription) | |
| 151 | + } | |
| 152 | + } | |
| 153 | + throw lastError | |
| 154 | + } | |
| 155 | + | |
| 156 | + // MARK: - Balances | |
| 157 | + | |
| 158 | + public func fetchBalances() async throws -> XRPLBalances { | |
| 159 | + guard let address else { throw WalletError.internalError("XRPL not configured.") } | |
| 160 | + var balances = XRPLBalances() | |
| 161 | + let info = try await rpc("account_info", ["account": address, "ledger_index": "validated"]) | |
| 162 | + if info["error"] as? String == "actNotFound" { | |
| 163 | + return balances // unfunded: first deposit must be ≥ 1 XRP | |
| 164 | + } | |
| 165 | + guard let accountData = info["account_data"] as? [String: Any] else { | |
| 166 | + throw WalletError.rpc((info["error_message"] as? String) ?? "account_info failed.") | |
| 167 | + } | |
| 168 | + balances.accountExists = true | |
| 169 | + balances.drops = (accountData["Balance"] as? String).flatMap(UInt64.init) ?? 0 | |
| 170 | + let ownerCount = (accountData["OwnerCount"] as? NSNumber)?.uint64Value ?? 0 | |
| 171 | + balances.reserveDrops = Self.baseReserveDrops + ownerCount * Self.ownerReserveDrops | |
| 172 | + | |
| 173 | + let lines = try await rpc("account_lines", ["account": address, "ledger_index": "validated"]) | |
| 174 | + for line in (lines["lines"] as? [[String: Any]]) ?? [] { | |
| 175 | + if line["currency"] as? String == Self.rlusdCurrencyHex, | |
| 176 | + line["account"] as? String == network.rlusdIssuer { | |
| 177 | + balances.hasRLUSDTrustline = true | |
| 178 | + balances.rlusdValue = (line["balance"] as? String) ?? "0" | |
| 179 | + } | |
| 180 | + } | |
| 181 | + return balances | |
| 182 | + } | |
| 183 | + | |
| 184 | + private func recipientHasRLUSDTrustline(_ recipient: String) async throws -> Bool { | |
| 185 | + if recipient == network.rlusdIssuer { return true } | |
| 186 | + let lines = try await rpc("account_lines", ["account": recipient, "ledger_index": "validated"]) | |
| 187 | + if lines["error"] as? String == "actNotFound" { return false } | |
| 188 | + for line in (lines["lines"] as? [[String: Any]]) ?? [] { | |
| 189 | + if line["currency"] as? String == Self.rlusdCurrencyHex, | |
| 190 | + line["account"] as? String == network.rlusdIssuer { | |
| 191 | + return true | |
| 192 | + } | |
| 193 | + } | |
| 194 | + return false | |
| 195 | + } | |
| 196 | + | |
| 197 | + // MARK: - Estimate | |
| 198 | + | |
| 199 | + public func estimateSend(to recipient: String, amountDrops: UInt64, | |
| 200 | + amountValue: String, isRLUSD: Bool) async throws -> PreparedXRPLSend { | |
| 201 | + guard Self.validate(address: recipient) else { throw WalletError.invalidAddress } | |
| 202 | + let feeResult = try await rpc("fee", [:]) | |
| 203 | + let openFee = ((feeResult["drops"] as? [String: Any])?["open_ledger_fee"] as? String) | |
| 204 | + .flatMap(UInt64.init) ?? 10 | |
| 205 | + let fee = max(10, min(openFee, 10_000)) // sane bounds | |
| 206 | + | |
| 207 | + var activates = false | |
| 208 | + if isRLUSD { | |
| 209 | + guard try await recipientHasRLUSDTrustline(recipient) else { | |
| 210 | + throw WalletError.internalError("The recipient has no RLUSD trustline — they must add one before they can receive RLUSD.") | |
| 211 | + } | |
| 212 | + } else { | |
| 213 | + let info = try await rpc("account_info", ["account": recipient, "ledger_index": "validated"]) | |
| 214 | + if info["error"] as? String == "actNotFound" { | |
| 215 | + activates = true | |
| 216 | + guard amountDrops >= Self.baseReserveDrops else { | |
| 217 | + throw WalletError.internalError("This account doesn't exist yet — the first payment must be at least 1 XRP (base reserve).") | |
| 218 | + } | |
| 219 | + } | |
| 220 | + } | |
| 221 | + return PreparedXRPLSend( | |
| 222 | + recipient: recipient, amountDrops: amountDrops, amountValue: amountValue, | |
| 223 | + isRLUSD: isRLUSD, feeDrops: fee, activatesRecipient: activates, network: network | |
| 224 | + ) | |
| 225 | + } | |
| 226 | + | |
| 227 | + // MARK: - Sign + submit | |
| 228 | + | |
| 229 | + private func signingContext() async throws -> (sequence: UInt32, lastLedger: UInt32) { | |
| 230 | + guard let address else { throw WalletError.internalError("XRPL not configured.") } | |
| 231 | + let info = try await rpc("account_info", ["account": address, "ledger_index": "validated"]) | |
| 232 | + guard let accountData = info["account_data"] as? [String: Any], | |
| 233 | + let sequence = (accountData["Sequence"] as? NSNumber)?.uint32Value, | |
| 234 | + let ledgerIndex = (info["ledger_index"] as? NSNumber)?.uint32Value else { | |
| 235 | + throw WalletError.rpc("Could not read the account sequence.") | |
| 236 | + } | |
| 237 | + return (sequence, ledgerIndex + 30) | |
| 238 | + } | |
| 239 | + | |
| 240 | + private func submit(_ input: RippleSigningInput) async throws -> String { | |
| 241 | + let output: RippleSigningOutput = AnySigner.sign(input: input, coin: .xrp) | |
| 242 | + guard output.error == .ok, !output.encoded.isEmpty else { | |
| 243 | + throw WalletError.signingFailed | |
| 244 | + } | |
| 245 | + let blob = output.encoded.map { String(format: "%02X", $0) }.joined() | |
| 246 | + let result = try await rpc("submit", ["tx_blob": blob]) | |
| 247 | + let engine = (result["engine_result"] as? String) ?? "unknown" | |
| 248 | + guard engine == "tesSUCCESS" || engine.hasPrefix("terQUEUED") else { | |
| 249 | + throw WalletError.rpc((result["engine_result_message"] as? String) ?? engine) | |
| 250 | + } | |
| 251 | + return ((result["tx_json"] as? [String: Any])?["hash"] as? String) ?? blob.prefix(64).lowercased() | |
| 252 | + } | |
| 253 | + | |
| 254 | + public func send(_ prepared: PreparedXRPLSend, mnemonic: String) async throws -> String { | |
| 255 | + guard let address else { throw WalletError.internalError("XRPL not configured.") } | |
| 256 | + guard let wallet = HDWallet(mnemonic: mnemonic, passphrase: "") else { | |
| 257 | + throw WalletError.invalidMnemonic | |
| 258 | + } | |
| 259 | + let context = try await signingContext() | |
| 260 | + | |
| 261 | + var payment = RippleOperationPayment() | |
| 262 | + payment.destination = prepared.recipient | |
| 263 | + if prepared.isRLUSD { | |
| 264 | + var currency = RippleCurrencyAmount() | |
| 265 | + currency.currency = Self.rlusdCurrencyHex | |
| 266 | + currency.value = prepared.amountValue | |
| 267 | + currency.issuer = prepared.network.rlusdIssuer | |
| 268 | + payment.currencyAmount = currency | |
| 269 | + } else { | |
| 270 | + payment.amount = Int64(prepared.amountDrops) | |
| 271 | + } | |
| 272 | + | |
| 273 | + var input = RippleSigningInput() | |
| 274 | + input.account = address | |
| 275 | + input.fee = Int64(prepared.feeDrops) | |
| 276 | + input.sequence = context.sequence | |
| 277 | + input.lastLedgerSequence = context.lastLedger | |
| 278 | + input.privateKey = wallet.getKeyForCoin(coin: .xrp).data | |
| 279 | + input.operationOneof = .opPayment(payment) | |
| 280 | + return try await submit(input) | |
| 281 | + } | |
| 282 | + | |
| 283 | + /// One-tap RLUSD trustline (costs the 12-drop fee + locks 0.2 XRP reserve). | |
| 284 | + public func createRLUSDTrustline(mnemonic: String) async throws -> String { | |
| 285 | + guard let address else { throw WalletError.internalError("XRPL not configured.") } | |
| 286 | + guard let wallet = HDWallet(mnemonic: mnemonic, passphrase: "") else { | |
| 287 | + throw WalletError.invalidMnemonic | |
| 288 | + } | |
| 289 | + let context = try await signingContext() | |
| 290 | + | |
| 291 | + var limit = RippleCurrencyAmount() | |
| 292 | + limit.currency = Self.rlusdCurrencyHex | |
| 293 | + limit.value = "1000000000" | |
| 294 | + limit.issuer = network.rlusdIssuer | |
| 295 | + var trustSet = RippleOperationTrustSet() | |
| 296 | + trustSet.limitAmount = limit | |
| 297 | + | |
| 298 | + var input = RippleSigningInput() | |
| 299 | + input.account = address | |
| 300 | + input.fee = 12 | |
| 301 | + input.sequence = context.sequence | |
| 302 | + input.lastLedgerSequence = context.lastLedger | |
| 303 | + input.flags = 131_072 // tfSetNoRipple | |
| 304 | + input.privateKey = wallet.getKeyForCoin(coin: .xrp).data | |
| 305 | + input.operationOneof = .opTrustSet(trustSet) | |
| 306 | + return try await submit(input) | |
| 307 | + } | |
| 308 | + | |
| 309 | + // MARK: - Formatting | |
| 310 | + | |
| 311 | + public static func formatXRP(_ drops: UInt64) -> String { | |
| 312 | + TokenAmount.format(BigUInt(drops), decimals: xrpDecimals) | |
| 313 | + } | |
| 314 | + | |
| 315 | + public static func parseXRP(_ input: String) -> UInt64? { | |
| 316 | + guard let units = TokenAmount.parse(input, decimals: xrpDecimals), units <= BigUInt(UInt64.max) else { return nil } | |
| 317 | + return UInt64(units) | |
| 318 | + } | |
| 319 | + | |
| 320 | + /// RLUSD values travel as decimal strings on-ledger; validate shape only. | |
| 321 | + public static func validRLUSDAmount(_ input: String) -> String? { | |
| 322 | + let normalized = input.trimmingCharacters(in: .whitespaces).replacingOccurrences(of: ",", with: ".") | |
| 323 | + guard TokenAmount.parse(normalized, decimals: 15) ?? 0 > 0 else { return nil } | |
| 324 | + return normalized | |
| 325 | + } | |
| 326 | +} | |
added
Sources/OSVaultKit/Utils/AddressValidator.swift
+43 −0
@@ -0,0 +1,43 @@ | ||
| 1 | +// | |
| 2 | +// AddressValidator.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import Web3Core | |
| 11 | + | |
| 12 | +/// Recipient address validation: hex shape + EIP-55 checksum. | |
| 13 | +/// All-lowercase (or all-uppercase) addresses carry no checksum information — | |
| 14 | +/// they are accepted with a warning, per the project security rules. | |
| 15 | +public enum AddressValidator { | |
| 16 | + | |
| 17 | + public enum Verdict: Equatable { | |
| 18 | + /// Mixed-case address whose EIP-55 checksum matches. | |
| 19 | + case valid(checksummed: String) | |
| 20 | + /// Well-formed but caseless — no checksum to verify. Warn, don't block. | |
| 21 | + case validNoChecksum(checksummed: String) | |
| 22 | + case invalid | |
| 23 | + } | |
| 24 | + | |
| 25 | + public static func validate(_ input: String) -> Verdict { | |
| 26 | + let candidate = input.trimmingCharacters(in: .whitespacesAndNewlines) | |
| 27 | + guard candidate.count == 42, candidate.hasPrefix("0x") else { return .invalid } | |
| 28 | + let body = String(candidate.dropFirst(2)) | |
| 29 | + guard body.allSatisfy({ $0.isHexDigit }) else { return .invalid } | |
| 30 | + guard let checksummed = EthereumAddress.toChecksumAddress(candidate) else { return .invalid } | |
| 31 | + | |
| 32 | + // An exact checksum match is valid even when it happens to be all one | |
| 33 | + // case (some EIP-55 checksums are, e.g. 0x529084…9EE7). | |
| 34 | + if candidate == checksummed { | |
| 35 | + return .valid(checksummed: checksummed) | |
| 36 | + } | |
| 37 | + let letters = body.filter { $0.isLetter } | |
| 38 | + let caseless = letters.isEmpty | |
| 39 | + || letters.allSatisfy { $0.isLowercase } | |
| 40 | + || letters.allSatisfy { $0.isUppercase } | |
| 41 | + return caseless ? .validNoChecksum(checksummed: checksummed) : .invalid | |
| 42 | + } | |
| 43 | +} | |
added
Sources/OSVaultKit/Utils/Hex.swift
+69 −0
@@ -0,0 +1,69 @@ | ||
| 1 | +// | |
| 2 | +// Hex.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Minimal hex helpers for JSON-RPC quantities and calldata. | |
| 13 | +public enum Hex { | |
| 14 | + | |
| 15 | + public static func quantity(_ value: BigUInt) -> String { | |
| 16 | + "0x" + String(value, radix: 16) | |
| 17 | + } | |
| 18 | + | |
| 19 | + public static func toBigUInt(_ hex: String) -> BigUInt? { | |
| 20 | + let stripped = hex.hasPrefix("0x") ? String(hex.dropFirst(2)) : hex | |
| 21 | + if stripped.isEmpty { return 0 } | |
| 22 | + return BigUInt(stripped, radix: 16) | |
| 23 | + } | |
| 24 | + | |
| 25 | + public static func data(_ hex: String) -> Data? { | |
| 26 | + var stripped = hex.hasPrefix("0x") ? String(hex.dropFirst(2)) : hex | |
| 27 | + if stripped.count % 2 != 0 { stripped = "0" + stripped } | |
| 28 | + var out = Data(capacity: stripped.count / 2) | |
| 29 | + var index = stripped.startIndex | |
| 30 | + 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 = next | |
| 35 | + } | |
| 36 | + return out | |
| 37 | + } | |
| 38 | + | |
| 39 | + public static func string(_ data: Data) -> String { | |
| 40 | + "0x" + data.map { String(format: "%02x", $0) }.joined() | |
| 41 | + } | |
| 42 | + | |
| 43 | + /// 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) + data | |
| 47 | + } | |
| 48 | + | |
| 49 | + public static func abiWord(_ value: BigUInt) -> Data { | |
| 50 | + abiWord(value.serialize()) | |
| 51 | + } | |
| 52 | + | |
| 53 | + /// 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 calldata | |
| 60 | + } | |
| 61 | + | |
| 62 | + /// 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 calldata | |
| 68 | + } | |
| 69 | +} | |
added
Sources/OSVaultKit/Utils/QRCode.swift
+25 −0
@@ -0,0 +1,25 @@ | ||
| 1 | +// | |
| 2 | +// QRCode.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import AppKit | |
| 10 | +import CoreImage | |
| 11 | + | |
| 12 | +enum QRCode { | |
| 13 | + /// Renders a crisp (non-interpolated) QR code for the given string. | |
| 14 | + static func image(for string: String, side: CGFloat = 240) -> NSImage? { | |
| 15 | + guard let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil } | |
| 16 | + filter.setValue(Data(string.utf8), forKey: "inputMessage") | |
| 17 | + filter.setValue("M", forKey: "inputCorrectionLevel") | |
| 18 | + guard let output = filter.outputImage else { return nil } | |
| 19 | + | |
| 20 | + let scale = side / output.extent.width | |
| 21 | + let scaled = output.transformed(by: CGAffineTransform(scaleX: scale, y: scale)) | |
| 22 | + guard let cgImage = CIContext().createCGImage(scaled, from: scaled.extent) else { return nil } | |
| 23 | + return NSImage(cgImage: cgImage, size: NSSize(width: side, height: side)) | |
| 24 | + } | |
| 25 | +} | |
added
Sources/OSVaultKit/Views/Bitcoin/BitcoinView.swift
+373 −0
@@ -0,0 +1,373 @@ | ||
| 1 | +// | |
| 2 | +// BitcoinView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Bitcoin panel: balance (confirmed/pending), receive with address rotation, | |
| 13 | +/// send with live fee presets from mempool.space, and the mainnet/signet | |
| 14 | +/// switch. Same security flow as EVM sends: password → sign → discard. | |
| 15 | +struct BitcoinView: View { | |
| 16 | + @EnvironmentObject var app: AppState | |
| 17 | + @Environment(\.dismiss) private var dismiss | |
| 18 | + | |
| 19 | + enum Mode { case overview, receive, send } | |
| 20 | + @State private var mode: Mode = .overview | |
| 21 | + | |
| 22 | + // Receive | |
| 23 | + @State private var receiveAddress: String? | |
| 24 | + | |
| 25 | + // Send | |
| 26 | + @State private var recipient = "" | |
| 27 | + @State private var amountInput = "" | |
| 28 | + @State private var fees: BitcoinService.FeeRates? | |
| 29 | + @State private var selectedRate: UInt64 = 2 | |
| 30 | + @State private var prepared: BitcoinService.PreparedBTCSend? | |
| 31 | + @State private var password = "" | |
| 32 | + @State private var sending = false | |
| 33 | + @State private var sentTxid: String? | |
| 34 | + @State private var errorMessage: String? | |
| 35 | + | |
| 36 | + // Network switch | |
| 37 | + @State private var switchPassword = "" | |
| 38 | + @State private var showNetworkSwitch = false | |
| 39 | + | |
| 40 | + var body: some View { | |
| 41 | + VStack(alignment: .leading, spacing: 16) { | |
| 42 | + header | |
| 43 | + switch mode { | |
| 44 | + case .overview: overview | |
| 45 | + case .receive: receive | |
| 46 | + case .send: send | |
| 47 | + } | |
| 48 | + } | |
| 49 | + .padding(24) | |
| 50 | + .frame(width: 470) | |
| 51 | + .onAppear { | |
| 52 | + Task { fees = await app.bitcoinService.recommendedFees() | |
| 53 | + selectedRate = fees?.halfHour ?? 2 } | |
| 54 | + } | |
| 55 | + } | |
| 56 | + | |
| 57 | + private var header: some View { | |
| 58 | + HStack { | |
| 59 | + Text("Bitcoin").font(.title2.bold()) | |
| 60 | + Spacer() | |
| 61 | + Text(app.btcNetwork.isTestnet ? "SIGNET · test" : "MAINNET") | |
| 62 | + .font(.caption.weight(.bold)) | |
| 63 | + .padding(.horizontal, 10).padding(.vertical, 4) | |
| 64 | + .background(app.btcNetwork.isTestnet ? Color.orange.opacity(0.25) : Color.yellow.opacity(0.25)) | |
| 65 | + .foregroundStyle(app.btcNetwork.isTestnet ? Color.orange : Color.yellow) | |
| 66 | + .clipShape(Capsule()) | |
| 67 | + Button("Done") { dismiss() } | |
| 68 | + } | |
| 69 | + } | |
| 70 | + | |
| 71 | + // MARK: - Overview | |
| 72 | + | |
| 73 | + private var overview: some View { | |
| 74 | + VStack(alignment: .leading, spacing: 14) { | |
| 75 | + VStack(alignment: .leading, spacing: 8) { | |
| 76 | + HStack(alignment: .firstTextBaseline) { | |
| 77 | + Text("BTC").font(.headline) | |
| 78 | + Spacer() | |
| 79 | + VStack(alignment: .trailing, spacing: 2) { | |
| 80 | + Text(BitcoinService.formatBTC(app.btcBalance?.totalSats ?? 0) + " BTC") | |
| 81 | + .font(.system(size: 26, weight: .bold, design: .rounded)) | |
| 82 | + .monospacedDigit() | |
| 83 | + if let fiat = btcFiat { | |
| 84 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 85 | + } | |
| 86 | + } | |
| 87 | + } | |
| 88 | + if let balance = app.btcBalance, balance.pendingSats > 0 { | |
| 89 | + Text("\(BitcoinService.formatBTC(balance.confirmedSats)) confirmed + \(BitcoinService.formatBTC(balance.pendingSats)) pending") | |
| 90 | + .font(.caption).foregroundStyle(.orange) | |
| 91 | + } | |
| 92 | + if app.btcSyncing { | |
| 93 | + HStack { ProgressView().controlSize(.small); Text("Syncing…").font(.caption).foregroundStyle(.secondary) } | |
| 94 | + } | |
| 95 | + if let error = app.btcError { | |
| 96 | + Label(error, systemImage: "wifi.exclamationmark") | |
| 97 | + .font(.caption).foregroundStyle(.orange) | |
| 98 | + } | |
| 99 | + } | |
| 100 | + .padding(14) | |
| 101 | + .background(.quaternary.opacity(0.4)) | |
| 102 | + .clipShape(RoundedRectangle(cornerRadius: 10)) | |
| 103 | + | |
| 104 | + HStack(spacing: 12) { | |
| 105 | + Button { | |
| 106 | + mode = .send | |
| 107 | + } label: { | |
| 108 | + Label("Send", systemImage: "arrow.up.circle.fill").frame(maxWidth: .infinity) | |
| 109 | + } | |
| 110 | + .buttonStyle(.borderedProminent) | |
| 111 | + Button { | |
| 112 | + mode = .receive | |
| 113 | + receiveAddress = nil | |
| 114 | + } label: { | |
| 115 | + Label("Receive", systemImage: "arrow.down.circle").frame(maxWidth: .infinity) | |
| 116 | + } | |
| 117 | + Button { | |
| 118 | + Task { await app.refreshBitcoin() } | |
| 119 | + } label: { | |
| 120 | + Image(systemName: "arrow.clockwise") | |
| 121 | + } | |
| 122 | + .help("Sync now") | |
| 123 | + } | |
| 124 | + | |
| 125 | + Text("Native SegWit (BIP-84) from your existing recovery phrase. Sync, fees and broadcast via mempool.space — keyless, with automatic fallback.") | |
| 126 | + .font(.caption) | |
| 127 | + .foregroundStyle(.secondary) | |
| 128 | + | |
| 129 | + DisclosureGroup("Network", isExpanded: $showNetworkSwitch) { | |
| 130 | + VStack(alignment: .leading, spacing: 8) { | |
| 131 | + Text("Switching re-derives your Bitcoin wallet on the other network. Enter your vault password to apply.") | |
| 132 | + .font(.caption).foregroundStyle(.secondary) | |
| 133 | + HStack { | |
| 134 | + SecureField("Vault password", text: $switchPassword) | |
| 135 | + .textFieldStyle(.roundedBorder) | |
| 136 | + Button(app.btcNetwork == .signet ? "Switch to mainnet" : "Switch to signet") { | |
| 137 | + switchNetwork() | |
| 138 | + } | |
| 139 | + .disabled(switchPassword.isEmpty) | |
| 140 | + } | |
| 141 | + } | |
| 142 | + .padding(.top, 6) | |
| 143 | + } | |
| 144 | + .font(.callout) | |
| 145 | + } | |
| 146 | + } | |
| 147 | + | |
| 148 | + private var btcFiat: String? { | |
| 149 | + guard app.pricesEnabled, let sats = app.btcBalance?.totalSats, sats > 0, | |
| 150 | + let price = app.fiatPrices["BTC"] else { return nil } | |
| 151 | + let value = PriceService.fiatValue(units: BigUInt(sats), decimals: 8, price: price) | |
| 152 | + return "≈ " + PriceService.formatFiat(value, currency: app.fiatCurrency) | |
| 153 | + } | |
| 154 | + | |
| 155 | + private func switchNetwork() { | |
| 156 | + let target: BitcoinService.BTCNetwork = app.btcNetwork == .signet ? .mainnet : .signet | |
| 157 | + let candidate = switchPassword | |
| 158 | + errorMessage = nil | |
| 159 | + Task { | |
| 160 | + do { | |
| 161 | + try await app.switchBitcoinNetwork(to: target, password: candidate) | |
| 162 | + switchPassword = "" | |
| 163 | + showNetworkSwitch = false | |
| 164 | + } catch { | |
| 165 | + errorMessage = error.localizedDescription | |
| 166 | + } | |
| 167 | + } | |
| 168 | + } | |
| 169 | + | |
| 170 | + // MARK: - Receive | |
| 171 | + | |
| 172 | + private var receive: some View { | |
| 173 | + VStack(spacing: 14) { | |
| 174 | + if let address = receiveAddress { | |
| 175 | + if let qr = QRCode.image(for: address) { | |
| 176 | + Image(nsImage: qr) | |
| 177 | + .interpolation(.none) | |
| 178 | + .resizable() | |
| 179 | + .frame(width: 200, height: 200) | |
| 180 | + .background(.white) | |
| 181 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 182 | + } | |
| 183 | + Text(address) | |
| 184 | + .font(.callout.monospaced()) | |
| 185 | + .textSelection(.enabled) | |
| 186 | + .padding(8) | |
| 187 | + .background(.quaternary.opacity(0.4)) | |
| 188 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 189 | + CopyButton(text: address) | |
| 190 | + Text("A fresh address is revealed on every use (privacy). Older addresses keep working.") | |
| 191 | + .font(.caption).foregroundStyle(.secondary) | |
| 192 | + .multilineTextAlignment(.center) | |
| 193 | + } else { | |
| 194 | + ProgressView() | |
| 195 | + } | |
| 196 | + if let errorMessage { | |
| 197 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 198 | + } | |
| 199 | + Button("Back") { mode = .overview } | |
| 200 | + } | |
| 201 | + .frame(maxWidth: .infinity) | |
| 202 | + .onAppear { | |
| 203 | + Task { | |
| 204 | + do { receiveAddress = try await app.bitcoinService.receiveAddress() } | |
| 205 | + catch { errorMessage = error.localizedDescription } | |
| 206 | + } | |
| 207 | + } | |
| 208 | + } | |
| 209 | + | |
| 210 | + // MARK: - Send | |
| 211 | + | |
| 212 | + private var send: some View { | |
| 213 | + VStack(alignment: .leading, spacing: 12) { | |
| 214 | + if let txid = sentTxid { | |
| 215 | + sentView(txid) | |
| 216 | + } else if let prepared { | |
| 217 | + confirmView(prepared) | |
| 218 | + } else { | |
| 219 | + sendForm | |
| 220 | + } | |
| 221 | + } | |
| 222 | + } | |
| 223 | + | |
| 224 | + private var sendForm: some View { | |
| 225 | + VStack(alignment: .leading, spacing: 12) { | |
| 226 | + TextField("Recipient (bc1q… / tb1q…)", text: $recipient) | |
| 227 | + .textFieldStyle(.roundedBorder) | |
| 228 | + .font(.body.monospaced()) | |
| 229 | + .autocorrectionDisabled() | |
| 230 | + if !recipient.isEmpty && !BitcoinService.validate(address: recipient, network: app.btcNetwork) { | |
| 231 | + Label("Not a valid \(app.btcNetwork.displayName) address", systemImage: "xmark.circle") | |
| 232 | + .font(.caption).foregroundStyle(.red) | |
| 233 | + } | |
| 234 | + HStack { | |
| 235 | + TextField("Amount", text: $amountInput) | |
| 236 | + .textFieldStyle(.roundedBorder) | |
| 237 | + .font(.body.monospaced()) | |
| 238 | + Text("BTC").foregroundStyle(.secondary) | |
| 239 | + } | |
| 240 | + Text("Balance: \(BitcoinService.formatBTC(app.btcBalance?.totalSats ?? 0)) BTC") | |
| 241 | + .font(.caption).foregroundStyle(.secondary) | |
| 242 | + | |
| 243 | + if let fees { | |
| 244 | + Picker("Fee", selection: $selectedRate) { | |
| 245 | + Text("Fast (~10 min) · \(fees.fastest) sat/vB").tag(fees.fastest) | |
| 246 | + Text("Normal (~30 min) · \(fees.halfHour) sat/vB").tag(fees.halfHour) | |
| 247 | + Text("Slow (~1 h) · \(fees.hour) sat/vB").tag(fees.hour) | |
| 248 | + Text("Economy · \(fees.economy) sat/vB").tag(fees.economy) | |
| 249 | + } | |
| 250 | + } | |
| 251 | + if let errorMessage { | |
| 252 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 253 | + } | |
| 254 | + HStack { | |
| 255 | + Button("Back") { mode = .overview; errorMessage = nil } | |
| 256 | + Spacer() | |
| 257 | + Button("Review") { prepare() } | |
| 258 | + .buttonStyle(.borderedProminent) | |
| 259 | + .disabled(!sendFormValid) | |
| 260 | + } | |
| 261 | + } | |
| 262 | + } | |
| 263 | + | |
| 264 | + private var sendFormValid: Bool { | |
| 265 | + BitcoinService.validate(address: recipient, network: app.btcNetwork) | |
| 266 | + && (BitcoinService.parseBTC(amountInput) ?? 0) > 0 | |
| 267 | + } | |
| 268 | + | |
| 269 | + private func prepare() { | |
| 270 | + guard let sats = BitcoinService.parseBTC(amountInput) else { return } | |
| 271 | + errorMessage = nil | |
| 272 | + let to = recipient.trimmingCharacters(in: .whitespacesAndNewlines) | |
| 273 | + let rate = selectedRate | |
| 274 | + Task { | |
| 275 | + do { | |
| 276 | + prepared = try await app.bitcoinService.prepareSend( | |
| 277 | + to: to, amountSats: sats, feeRateSatVb: rate) | |
| 278 | + } catch { | |
| 279 | + errorMessage = error.localizedDescription | |
| 280 | + } | |
| 281 | + } | |
| 282 | + } | |
| 283 | + | |
| 284 | + private func confirmView(_ p: BitcoinService.PreparedBTCSend) -> some View { | |
| 285 | + VStack(alignment: .leading, spacing: 12) { | |
| 286 | + Text("Confirm transaction").font(.headline) | |
| 287 | + Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 8) { | |
| 288 | + GridRow { | |
| 289 | + Text("Recipient").foregroundStyle(.secondary) | |
| 290 | + Text(p.recipient).font(.callout.monospaced()).textSelection(.enabled) | |
| 291 | + } | |
| 292 | + GridRow { | |
| 293 | + Text("Amount").foregroundStyle(.secondary) | |
| 294 | + Text("\(BitcoinService.formatBTC(p.amountSats)) BTC").fontWeight(.semibold) | |
| 295 | + } | |
| 296 | + GridRow { | |
| 297 | + Text("Network").foregroundStyle(.secondary) | |
| 298 | + Text(p.network.displayName) | |
| 299 | + } | |
| 300 | + GridRow { | |
| 301 | + Text("Fee").foregroundStyle(.secondary) | |
| 302 | + Text("\(BitcoinService.formatBTC(p.feeSats)) BTC (\(p.feeRateSatVb) sat/vB)") | |
| 303 | + } | |
| 304 | + GridRow { | |
| 305 | + Text("Total").foregroundStyle(.secondary) | |
| 306 | + Text("\(BitcoinService.formatBTC(p.amountSats + p.feeSats)) BTC") | |
| 307 | + } | |
| 308 | + } | |
| 309 | + .font(.callout) | |
| 310 | + Divider() | |
| 311 | + SecureField("Vault password to sign", text: $password) | |
| 312 | + .textFieldStyle(.roundedBorder) | |
| 313 | + if let errorMessage { | |
| 314 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 315 | + } | |
| 316 | + HStack { | |
| 317 | + Button("Back") { | |
| 318 | + prepared = nil | |
| 319 | + password = "" | |
| 320 | + Task { await app.bitcoinService.cancelPending() } | |
| 321 | + } | |
| 322 | + Spacer() | |
| 323 | + if sending { ProgressView().controlSize(.small) } | |
| 324 | + Button("Sign & send") { broadcast() } | |
| 325 | + .buttonStyle(.borderedProminent) | |
| 326 | + .disabled(password.isEmpty || sending) | |
| 327 | + } | |
| 328 | + } | |
| 329 | + } | |
| 330 | + | |
| 331 | + private func broadcast() { | |
| 332 | + sending = true | |
| 333 | + errorMessage = nil | |
| 334 | + let candidate = password | |
| 335 | + let manager = app.keyManager | |
| 336 | + Task { | |
| 337 | + do { | |
| 338 | + let mnemonic = try await Task.detached { | |
| 339 | + try manager.unlock(password: candidate).mnemonic | |
| 340 | + }.value | |
| 341 | + let txid = try await app.bitcoinService.signAndBroadcast(mnemonic: mnemonic) | |
| 342 | + password = "" | |
| 343 | + sentTxid = txid | |
| 344 | + await app.refreshBitcoin() | |
| 345 | + } catch { | |
| 346 | + errorMessage = error.localizedDescription | |
| 347 | + } | |
| 348 | + sending = false | |
| 349 | + } | |
| 350 | + } | |
| 351 | + | |
| 352 | + private func sentView(_ txid: String) -> some View { | |
| 353 | + VStack(spacing: 12) { | |
| 354 | + Image(systemName: "paperplane.circle.fill") | |
| 355 | + .font(.system(size: 38)).foregroundStyle(.green) | |
| 356 | + Text("Transaction broadcast").font(.headline) | |
| 357 | + Text(txid) | |
| 358 | + .font(.caption.monospaced()) | |
| 359 | + .textSelection(.enabled) | |
| 360 | + .lineLimit(1).truncationMode(.middle) | |
| 361 | + Link("View on mempool.space", destination: app.btcNetwork.explorerTxURL(txid)) | |
| 362 | + Button("Done") { | |
| 363 | + sentTxid = nil | |
| 364 | + prepared = nil | |
| 365 | + recipient = "" | |
| 366 | + amountInput = "" | |
| 367 | + mode = .overview | |
| 368 | + } | |
| 369 | + .buttonStyle(.borderedProminent) | |
| 370 | + } | |
| 371 | + .frame(maxWidth: .infinity) | |
| 372 | + } | |
| 373 | +} | |
added
Sources/OSVaultKit/Views/Home/HomeView.swift
+254 −0
@@ -0,0 +1,254 @@ | ||
| 1 | +// | |
| 2 | +// HomeView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +struct HomeView: View { | |
| 13 | + @EnvironmentObject var app: AppState | |
| 14 | + @State private var showSend = false | |
| 15 | + @State private var showReceive = false | |
| 16 | + @State private var showSettings = false | |
| 17 | + @State private var showBitcoin = false | |
| 18 | + @State private var showSolana = false | |
| 19 | + @State private var showTron = false | |
| 20 | + @State private var showXRPL = false | |
| 21 | + @State private var showTON = false | |
| 22 | + | |
| 23 | + var body: some View { | |
| 24 | + VStack(spacing: 0) { | |
| 25 | + header | |
| 26 | + Divider() | |
| 27 | + ScrollView { | |
| 28 | + VStack(spacing: 16) { | |
| 29 | + balanceCard | |
| 30 | + if lowOnGas { | |
| 31 | + gasWarning | |
| 32 | + } | |
| 33 | + actionButtons | |
| 34 | + historySection | |
| 35 | + } | |
| 36 | + .padding(20) | |
| 37 | + } | |
| 38 | + } | |
| 39 | + .sheet(isPresented: $showSend) { SendView() } | |
| 40 | + .sheet(isPresented: $showReceive) { ReceiveView() } | |
| 41 | + .sheet(isPresented: $showSettings) { SettingsView() } | |
| 42 | + .sheet(isPresented: $showBitcoin) { BitcoinView() } | |
| 43 | + .sheet(isPresented: $showSolana) { SolanaView() } | |
| 44 | + .sheet(isPresented: $showTron) { TronView() } | |
| 45 | + .sheet(isPresented: $showXRPL) { XRPLView() } | |
| 46 | + .sheet(isPresented: $showTON) { TONView() } | |
| 47 | + } | |
| 48 | + | |
| 49 | + private var header: some View { | |
| 50 | + HStack { | |
| 51 | + NetworkBadge(network: app.network) | |
| 52 | + Spacer() | |
| 53 | + if let address = app.address { | |
| 54 | + Text(address.shortAddress) | |
| 55 | + .font(.callout.monospaced()) | |
| 56 | + .foregroundStyle(.secondary) | |
| 57 | + CopyButton(text: address) | |
| 58 | + .labelStyle(.iconOnly) | |
| 59 | + .buttonStyle(.borderless) | |
| 60 | + } | |
| 61 | + Menu { | |
| 62 | + Button("Bitcoin") { showBitcoin = true } | |
| 63 | + Button("Solana") { showSolana = true } | |
| 64 | + Button("Tron") { showTron = true } | |
| 65 | + Button("XRP Ledger") { showXRPL = true } | |
| 66 | + Button("TON") { showTON = true } | |
| 67 | + } label: { | |
| 68 | + Image(systemName: "link.circle") | |
| 69 | + } | |
| 70 | + .menuStyle(.borderlessButton) | |
| 71 | + .frame(width: 40) | |
| 72 | + .help("Other chains") | |
| 73 | + Button { | |
| 74 | + showSettings = true | |
| 75 | + } label: { | |
| 76 | + Image(systemName: "gearshape") | |
| 77 | + } | |
| 78 | + .buttonStyle(.borderless) | |
| 79 | + Button { | |
| 80 | + app.lock() | |
| 81 | + } label: { | |
| 82 | + Image(systemName: "lock.fill") | |
| 83 | + } | |
| 84 | + .buttonStyle(.borderless) | |
| 85 | + .help("Lock the vault") | |
| 86 | + } | |
| 87 | + .padding(.horizontal, 20) | |
| 88 | + .padding(.vertical, 12) | |
| 89 | + } | |
| 90 | + | |
| 91 | + private var tokens: [Token] { Token.available(on: app.network) } | |
| 92 | + | |
| 93 | + private var balanceCard: some View { | |
| 94 | + VStack(alignment: .leading, spacing: 12) { | |
| 95 | + if !app.balancesLoaded && app.balanceError == nil { | |
| 96 | + HStack { | |
| 97 | + ProgressView().controlSize(.small) | |
| 98 | + Text("Loading balances…").foregroundStyle(.secondary) | |
| 99 | + } | |
| 100 | + } | |
| 101 | + if let error = app.balanceError, !app.balancesLoaded { | |
| 102 | + Label(error, systemImage: "wifi.exclamationmark") | |
| 103 | + .foregroundStyle(.orange) | |
| 104 | + .font(.callout) | |
| 105 | + } | |
| 106 | + ForEach(tokens) { token in | |
| 107 | + HStack(alignment: .firstTextBaseline) { | |
| 108 | + Text(token.symbol).font(.headline) | |
| 109 | + Text(token.name).font(.caption).foregroundStyle(.secondary) | |
| 110 | + Spacer() | |
| 111 | + VStack(alignment: .trailing, spacing: 2) { | |
| 112 | + Text(TokenAmount.format(app.balances.tokenUnits[token.symbol] ?? 0, | |
| 113 | + decimals: token.decimals, maxFractionDigits: 6)) | |
| 114 | + .font(token.symbol == "USDC" ? .system(size: 28, weight: .bold, design: .rounded) | |
| 115 | + : .title3.weight(.semibold)) | |
| 116 | + .monospacedDigit() | |
| 117 | + if let fiat = fiatLine(units: app.balances.tokenUnits[token.symbol] ?? 0, | |
| 118 | + decimals: token.decimals, symbol: token.symbol) { | |
| 119 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 120 | + } | |
| 121 | + } | |
| 122 | + } | |
| 123 | + } | |
| 124 | + Divider() | |
| 125 | + HStack { | |
| 126 | + Text("\(app.network.config.nativeSymbol) (gas)").font(.subheadline).foregroundStyle(.secondary) | |
| 127 | + Spacer() | |
| 128 | + VStack(alignment: .trailing, spacing: 2) { | |
| 129 | + Text(TokenAmount.formatWei(app.balances.ethWei, maxFractionDigits: 6) + " " + app.network.config.nativeSymbol) | |
| 130 | + .font(.subheadline.monospaced()) | |
| 131 | + .foregroundStyle(.secondary) | |
| 132 | + if let fiat = fiatLine(units: app.balances.ethWei, decimals: 18, | |
| 133 | + symbol: app.network.config.nativeSymbol) { | |
| 134 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 135 | + } | |
| 136 | + } | |
| 137 | + } | |
| 138 | + if let error = app.balanceError, app.balancesLoaded { | |
| 139 | + Text("Refresh failed: \(error)").font(.caption).foregroundStyle(.orange) | |
| 140 | + } | |
| 141 | + } | |
| 142 | + .padding(16) | |
| 143 | + .background(.quaternary.opacity(0.4)) | |
| 144 | + .clipShape(RoundedRectangle(cornerRadius: 12)) | |
| 145 | + } | |
| 146 | + | |
| 147 | + private func fiatLine(units: BigUInt, decimals: Int, symbol: String) -> String? { | |
| 148 | + guard app.pricesEnabled, units > 0, let price = app.fiatPrices[symbol] else { return nil } | |
| 149 | + let value = PriceService.fiatValue(units: units, decimals: decimals, price: price) | |
| 150 | + return "≈ " + PriceService.formatFiat(value, currency: app.fiatCurrency) | |
| 151 | + } | |
| 152 | + | |
| 153 | + private var lowOnGas: Bool { | |
| 154 | + // Rough per-chain floor for one ERC-20 transfer; refined at send time. | |
| 155 | + guard app.balancesLoaded else { return false } | |
| 156 | + let floor: BigUInt | |
| 157 | + switch app.network { | |
| 158 | + case .polygon, .bnb, .avalanche, .gnosis: floor = 5_000_000_000_000_000 // 0.005 native | |
| 159 | + case .ethereum: floor = 1_000_000_000_000_000 // 0.001 ETH | |
| 160 | + default: floor = 30_000_000_000_000 // cheap L2s | |
| 161 | + } | |
| 162 | + return app.balances.ethWei < floor | |
| 163 | + } | |
| 164 | + | |
| 165 | + private var gasWarning: some View { | |
| 166 | + Label("\(app.network.config.nativeSymbol) balance is very low. Gas is paid in \(app.network.config.nativeSymbol) — sends may fail until you top up.", | |
| 167 | + systemImage: "fuelpump.slash") | |
| 168 | + .font(.callout) | |
| 169 | + .foregroundStyle(.orange) | |
| 170 | + .frame(maxWidth: .infinity, alignment: .leading) | |
| 171 | + .padding(12) | |
| 172 | + .background(Color.orange.opacity(0.12)) | |
| 173 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 174 | + } | |
| 175 | + | |
| 176 | + private var actionButtons: some View { | |
| 177 | + HStack(spacing: 12) { | |
| 178 | + Button { | |
| 179 | + showSend = true | |
| 180 | + } label: { | |
| 181 | + Label("Send", systemImage: "arrow.up.circle.fill") | |
| 182 | + .frame(maxWidth: .infinity) | |
| 183 | + } | |
| 184 | + .buttonStyle(.borderedProminent) | |
| 185 | + .controlSize(.large) | |
| 186 | + | |
| 187 | + Button { | |
| 188 | + showReceive = true | |
| 189 | + } label: { | |
| 190 | + Label("Receive", systemImage: "arrow.down.circle") | |
| 191 | + .frame(maxWidth: .infinity) | |
| 192 | + } | |
| 193 | + .controlSize(.large) | |
| 194 | + | |
| 195 | + Button { | |
| 196 | + Task { await app.refreshBalances() } | |
| 197 | + } label: { | |
| 198 | + Image(systemName: "arrow.clockwise") | |
| 199 | + } | |
| 200 | + .controlSize(.large) | |
| 201 | + .help("Refresh balances") | |
| 202 | + } | |
| 203 | + } | |
| 204 | + | |
| 205 | + private var historySection: some View { | |
| 206 | + VStack(alignment: .leading, spacing: 8) { | |
| 207 | + Text("Activity").font(.headline) | |
| 208 | + let visible = app.history.filter { $0.network == app.network } | |
| 209 | + if visible.isEmpty { | |
| 210 | + Text("Sends from this app will appear here. Full history is on the explorer.") | |
| 211 | + .font(.callout) | |
| 212 | + .foregroundStyle(.secondary) | |
| 213 | + } | |
| 214 | + ForEach(visible) { record in | |
| 215 | + HStack { | |
| 216 | + statusIcon(record.status) | |
| 217 | + VStack(alignment: .leading, spacing: 2) { | |
| 218 | + Text("Sent \(record.displayAmount) \(record.tokenSymbol)") | |
| 219 | + .font(.callout.weight(.medium)) | |
| 220 | + Text("to \(record.recipient.shortAddress) · \(record.date.formatted(date: .abbreviated, time: .shortened))") | |
| 221 | + .font(.caption) | |
| 222 | + .foregroundStyle(.secondary) | |
| 223 | + } | |
| 224 | + Spacer() | |
| 225 | + Link(destination: record.explorerURL) { | |
| 226 | + Image(systemName: "arrow.up.right.square") | |
| 227 | + } | |
| 228 | + .help("View on the explorer") | |
| 229 | + } | |
| 230 | + .padding(10) | |
| 231 | + .background(.quaternary.opacity(0.3)) | |
| 232 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 233 | + } | |
| 234 | + if let address = app.address { | |
| 235 | + Link("View full history on the explorer", | |
| 236 | + destination: app.network.explorerAddressURL(address)) | |
| 237 | + .font(.callout) | |
| 238 | + .padding(.top, 4) | |
| 239 | + } | |
| 240 | + } | |
| 241 | + .frame(maxWidth: .infinity, alignment: .leading) | |
| 242 | + } | |
| 243 | + | |
| 244 | + private func statusIcon(_ status: TransactionRecord.Status) -> some View { | |
| 245 | + switch status { | |
| 246 | + case .pending: | |
| 247 | + return Image(systemName: "clock").foregroundStyle(Color.orange) | |
| 248 | + case .confirmed: | |
| 249 | + return Image(systemName: "checkmark.circle.fill").foregroundStyle(Color.green) | |
| 250 | + case .failed: | |
| 251 | + return Image(systemName: "xmark.circle.fill").foregroundStyle(Color.red) | |
| 252 | + } | |
| 253 | + } | |
| 254 | +} | |
added
Sources/OSVaultKit/Views/Onboarding/OnboardingView.swift
+307 −0
@@ -0,0 +1,307 @@ | ||
| 1 | +// | |
| 2 | +// OnboardingView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | + | |
| 11 | +/// Create-wallet flow: password → show mnemonic → verify 3 random words → | |
| 12 | +/// vault written. Import flow: phrase + password. The vault is only written | |
| 13 | +/// after backup verification succeeds (create) or the phrase validates (import). | |
| 14 | +struct OnboardingView: View { | |
| 15 | + @EnvironmentObject var app: AppState | |
| 16 | + | |
| 17 | + enum Step { | |
| 18 | + case welcome | |
| 19 | + case setPassword(importing: Bool) | |
| 20 | + case showMnemonic | |
| 21 | + case verifyMnemonic | |
| 22 | + case importPhrase | |
| 23 | + } | |
| 24 | + | |
| 25 | + @State private var step: Step = .welcome | |
| 26 | + @State private var password = "" | |
| 27 | + @State private var passwordConfirm = "" | |
| 28 | + @State private var mnemonic = "" | |
| 29 | + @State private var importInput = "" | |
| 30 | + @State private var verifyIndices: [Int] = [] | |
| 31 | + @State private var verifyInputs: [String] = ["", "", ""] | |
| 32 | + @State private var errorMessage: String? | |
| 33 | + | |
| 34 | + var body: some View { | |
| 35 | + VStack(spacing: 0) { | |
| 36 | + content | |
| 37 | + } | |
| 38 | + .padding(32) | |
| 39 | + .frame(maxWidth: .infinity, maxHeight: .infinity) | |
| 40 | + } | |
| 41 | + | |
| 42 | + @ViewBuilder | |
| 43 | + private var content: some View { | |
| 44 | + switch step { | |
| 45 | + case .welcome: welcome | |
| 46 | + case .setPassword(let importing): setPassword(importing: importing) | |
| 47 | + case .showMnemonic: showMnemonic | |
| 48 | + case .verifyMnemonic: verifyMnemonic | |
| 49 | + case .importPhrase: importPhrase | |
| 50 | + } | |
| 51 | + } | |
| 52 | + | |
| 53 | + // MARK: - Welcome | |
| 54 | + | |
| 55 | + private var welcome: some View { | |
| 56 | + VStack(spacing: 20) { | |
| 57 | + Image(systemName: "lock.shield") | |
| 58 | + .font(.system(size: 56)) | |
| 59 | + .foregroundStyle(.blue) | |
| 60 | + Text("OS Vault").font(.largeTitle.bold()) | |
| 61 | + Text("Self-custody wallet for stablecoins, ETH and Bitcoin —\n11 EVM chains + Bitcoin from one recovery phrase.\nKeys are encrypted locally with OS Vault's own vault format; they never leave this Mac.") | |
| 62 | + .multilineTextAlignment(.center) | |
| 63 | + .foregroundStyle(.secondary) | |
| 64 | + VStack(spacing: 12) { | |
| 65 | + Button("Create a new wallet") { | |
| 66 | + step = .setPassword(importing: false) | |
| 67 | + } | |
| 68 | + .buttonStyle(.borderedProminent) | |
| 69 | + .controlSize(.large) | |
| 70 | + Button("Import an existing wallet") { | |
| 71 | + step = .setPassword(importing: true) | |
| 72 | + } | |
| 73 | + .controlSize(.large) | |
| 74 | + } | |
| 75 | + .padding(.top, 8) | |
| 76 | + } | |
| 77 | + } | |
| 78 | + | |
| 79 | + // MARK: - Password | |
| 80 | + | |
| 81 | + private func setPassword(importing: Bool) -> some View { | |
| 82 | + VStack(alignment: .leading, spacing: 16) { | |
| 83 | + Text("Choose a vault password").font(.title2.bold()) | |
| 84 | + Text("This password encrypts your recovery phrase on this Mac (AES-256-GCM). It cannot be recovered — if you forget it, only your recovery phrase can restore the wallet.") | |
| 85 | + .foregroundStyle(.secondary) | |
| 86 | + SecureField("Password (min. 8 characters)", text: $password) | |
| 87 | + .textFieldStyle(.roundedBorder) | |
| 88 | + SecureField("Confirm password", text: $passwordConfirm) | |
| 89 | + .textFieldStyle(.roundedBorder) | |
| 90 | + if let errorMessage { | |
| 91 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 92 | + } | |
| 93 | + HStack { | |
| 94 | + Button("Back") { | |
| 95 | + reset() | |
| 96 | + } | |
| 97 | + Spacer() | |
| 98 | + Button("Continue") { | |
| 99 | + guard password.count >= 8 else { | |
| 100 | + errorMessage = "Password must be at least 8 characters." | |
| 101 | + return | |
| 102 | + } | |
| 103 | + guard password == passwordConfirm else { | |
| 104 | + errorMessage = "Passwords do not match." | |
| 105 | + return | |
| 106 | + } | |
| 107 | + errorMessage = nil | |
| 108 | + if importing { | |
| 109 | + step = .importPhrase | |
| 110 | + } else { | |
| 111 | + do { | |
| 112 | + mnemonic = try app.keyManager.generateMnemonic() | |
| 113 | + step = .showMnemonic | |
| 114 | + } catch { | |
| 115 | + errorMessage = error.localizedDescription | |
| 116 | + } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + .buttonStyle(.borderedProminent) | |
| 120 | + } | |
| 121 | + } | |
| 122 | + .frame(maxWidth: 420) | |
| 123 | + } | |
| 124 | + | |
| 125 | + // MARK: - Show mnemonic | |
| 126 | + | |
| 127 | + private var mnemonicWords: [String] { mnemonic.split(separator: " ").map(String.init) } | |
| 128 | + | |
| 129 | + private var showMnemonic: some View { | |
| 130 | + VStack(alignment: .leading, spacing: 16) { | |
| 131 | + Text("Your recovery phrase").font(.title2.bold()) | |
| 132 | + Text("Write these 12 words down on paper, in order. Anyone with these words controls your funds. OS Vault will never show them again without your password.") | |
| 133 | + .foregroundStyle(.secondary) | |
| 134 | + LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 10) { | |
| 135 | + ForEach(Array(mnemonicWords.enumerated()), id: \.offset) { index, word in | |
| 136 | + HStack { | |
| 137 | + Text("\(index + 1).").foregroundStyle(.secondary).monospacedDigit() | |
| 138 | + Text(word).fontWeight(.medium) | |
| 139 | + Spacer() | |
| 140 | + } | |
| 141 | + .padding(8) | |
| 142 | + .background(.quaternary.opacity(0.5)) | |
| 143 | + .clipShape(RoundedRectangle(cornerRadius: 6)) | |
| 144 | + } | |
| 145 | + } | |
| 146 | + HStack { | |
| 147 | + Button("Back") { step = .setPassword(importing: false) } | |
| 148 | + Spacer() | |
| 149 | + Button("I wrote it down — verify") { | |
| 150 | + verifyIndices = Array(0..<12).shuffled().prefix(3).sorted() | |
| 151 | + verifyInputs = ["", "", ""] | |
| 152 | + errorMessage = nil | |
| 153 | + step = .verifyMnemonic | |
| 154 | + } | |
| 155 | + .buttonStyle(.borderedProminent) | |
| 156 | + } | |
| 157 | + } | |
| 158 | + .frame(maxWidth: 480) | |
| 159 | + } | |
| 160 | + | |
| 161 | + // MARK: - Verify backup | |
| 162 | + | |
| 163 | + private var verifyMnemonic: some View { | |
| 164 | + VStack(alignment: .leading, spacing: 16) { | |
| 165 | + Text("Verify your backup").font(.title2.bold()) | |
| 166 | + Text("Enter the requested words from your written backup.") | |
| 167 | + .foregroundStyle(.secondary) | |
| 168 | + ForEach(0..<3, id: \.self) { slot in | |
| 169 | + HStack { | |
| 170 | + Text("Word #\(verifyIndices[slot] + 1)") | |
| 171 | + .frame(width: 90, alignment: .leading) | |
| 172 | + TextField("word", text: $verifyInputs[slot]) | |
| 173 | + .textFieldStyle(.roundedBorder) | |
| 174 | + .autocorrectionDisabled() | |
| 175 | + } | |
| 176 | + } | |
| 177 | + if let errorMessage { | |
| 178 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 179 | + } | |
| 180 | + HStack { | |
| 181 | + Button("Show phrase again") { step = .showMnemonic } | |
| 182 | + Spacer() | |
| 183 | + Button("Confirm") { finishCreate() } | |
| 184 | + .buttonStyle(.borderedProminent) | |
| 185 | + } | |
| 186 | + } | |
| 187 | + .frame(maxWidth: 420) | |
| 188 | + } | |
| 189 | + | |
| 190 | + private func finishCreate() { | |
| 191 | + let words = mnemonicWords | |
| 192 | + for slot in 0..<3 { | |
| 193 | + let expected = words[verifyIndices[slot]] | |
| 194 | + let given = verifyInputs[slot].trimmingCharacters(in: .whitespacesAndNewlines).lowercased() | |
| 195 | + guard given == expected else { | |
| 196 | + errorMessage = "Word #\(verifyIndices[slot] + 1) does not match. Check your backup." | |
| 197 | + return | |
| 198 | + } | |
| 199 | + } | |
| 200 | + persist(mnemonic: mnemonic) | |
| 201 | + } | |
| 202 | + | |
| 203 | + // MARK: - Import | |
| 204 | + | |
| 205 | + private var importPhrase: some View { | |
| 206 | + VStack(alignment: .leading, spacing: 16) { | |
| 207 | + Text("Import wallet").font(.title2.bold()) | |
| 208 | + Text("Enter your 12- or 24-word recovery phrase, separated by spaces.") | |
| 209 | + .foregroundStyle(.secondary) | |
| 210 | + TextEditor(text: $importInput) | |
| 211 | + .font(.body.monospaced()) | |
| 212 | + .frame(height: 90) | |
| 213 | + .overlay(RoundedRectangle(cornerRadius: 6).stroke(.quaternary)) | |
| 214 | + .autocorrectionDisabled() | |
| 215 | + if let errorMessage { | |
| 216 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 217 | + } | |
| 218 | + HStack { | |
| 219 | + Button("Back") { step = .setPassword(importing: true) } | |
| 220 | + Spacer() | |
| 221 | + Button("Import") { | |
| 222 | + guard KeyManager.validate(mnemonic: importInput) else { | |
| 223 | + errorMessage = WalletError.invalidMnemonic.errorDescription | |
| 224 | + return | |
| 225 | + } | |
| 226 | + persist(mnemonic: importInput) | |
| 227 | + } | |
| 228 | + .buttonStyle(.borderedProminent) | |
| 229 | + } | |
| 230 | + } | |
| 231 | + .frame(maxWidth: 480) | |
| 232 | + } | |
| 233 | + | |
| 234 | + // MARK: - Common | |
| 235 | + | |
| 236 | + private func persist(mnemonic: String) { | |
| 237 | + do { | |
| 238 | + let wallet = try app.keyManager.saveWallet(mnemonic: mnemonic, password: password) | |
| 239 | + reset() | |
| 240 | + app.didUnlock(wallet: wallet) | |
| 241 | + } catch { | |
| 242 | + errorMessage = error.localizedDescription | |
| 243 | + } | |
| 244 | + } | |
| 245 | + | |
| 246 | + private func reset() { | |
| 247 | + password = "" | |
| 248 | + passwordConfirm = "" | |
| 249 | + mnemonic = "" | |
| 250 | + importInput = "" | |
| 251 | + verifyInputs = ["", "", ""] | |
| 252 | + errorMessage = nil | |
| 253 | + step = .welcome | |
| 254 | + } | |
| 255 | +} | |
| 256 | + | |
| 257 | +/// Lock screen for an existing vault. | |
| 258 | +struct UnlockView: View { | |
| 259 | + @EnvironmentObject var app: AppState | |
| 260 | + @State private var password = "" | |
| 261 | + @State private var errorMessage: String? | |
| 262 | + @State private var unlocking = false | |
| 263 | + | |
| 264 | + var body: some View { | |
| 265 | + VStack(spacing: 20) { | |
| 266 | + Image(systemName: "lock.fill") | |
| 267 | + .font(.system(size: 44)) | |
| 268 | + .foregroundStyle(.blue) | |
| 269 | + Text("OS Vault is locked").font(.title2.bold()) | |
| 270 | + SecureField("Vault password", text: $password) | |
| 271 | + .textFieldStyle(.roundedBorder) | |
| 272 | + .frame(maxWidth: 280) | |
| 273 | + .onSubmit(unlock) | |
| 274 | + if let errorMessage { | |
| 275 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 276 | + } | |
| 277 | + Button(unlocking ? "Unlocking…" : "Unlock") { unlock() } | |
| 278 | + .buttonStyle(.borderedProminent) | |
| 279 | + .controlSize(.large) | |
| 280 | + .disabled(unlocking || password.isEmpty) | |
| 281 | + } | |
| 282 | + .padding(32) | |
| 283 | + .frame(maxWidth: .infinity, maxHeight: .infinity) | |
| 284 | + } | |
| 285 | + | |
| 286 | + private func unlock() { | |
| 287 | + guard !password.isEmpty else { return } | |
| 288 | + unlocking = true | |
| 289 | + errorMessage = nil | |
| 290 | + let manager = app.keyManager | |
| 291 | + let candidate = password | |
| 292 | + Task.detached { | |
| 293 | + // PBKDF2 at 600k rounds is deliberately slow; keep it off the main thread. | |
| 294 | + let result = Result { try manager.unlock(password: candidate) } | |
| 295 | + await MainActor.run { | |
| 296 | + unlocking = false | |
| 297 | + switch result { | |
| 298 | + case .success(let wallet): | |
| 299 | + password = "" | |
| 300 | + app.didUnlock(wallet: wallet) | |
| 301 | + case .failure(let error): | |
| 302 | + errorMessage = error.localizedDescription | |
| 303 | + } | |
| 304 | + } | |
| 305 | + } | |
| 306 | + } | |
| 307 | +} | |
added
Sources/OSVaultKit/Views/Receive/ReceiveView.swift
+49 −0
@@ -0,0 +1,49 @@ | ||
| 1 | +// | |
| 2 | +// ReceiveView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | + | |
| 11 | +struct ReceiveView: View { | |
| 12 | + @EnvironmentObject var app: AppState | |
| 13 | + @Environment(\.dismiss) private var dismiss | |
| 14 | + | |
| 15 | + var body: some View { | |
| 16 | + VStack(spacing: 16) { | |
| 17 | + HStack { | |
| 18 | + Text("Receive").font(.title2.bold()) | |
| 19 | + Spacer() | |
| 20 | + NetworkBadge(network: app.network) | |
| 21 | + } | |
| 22 | + if let address = app.address { | |
| 23 | + if let qr = QRCode.image(for: address) { | |
| 24 | + Image(nsImage: qr) | |
| 25 | + .interpolation(.none) | |
| 26 | + .resizable() | |
| 27 | + .frame(width: 220, height: 220) | |
| 28 | + .background(.white) | |
| 29 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 30 | + } | |
| 31 | + Text(address) | |
| 32 | + .font(.callout.monospaced()) | |
| 33 | + .textSelection(.enabled) | |
| 34 | + .padding(10) | |
| 35 | + .background(.quaternary.opacity(0.4)) | |
| 36 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 37 | + CopyButton(text: address) | |
| 38 | + Text("Send only assets on \(app.network.config.displayName) (chain ID \(String(app.network.config.chainID))) to this address.") | |
| 39 | + .font(.caption) | |
| 40 | + .foregroundStyle(.secondary) | |
| 41 | + .multilineTextAlignment(.center) | |
| 42 | + } | |
| 43 | + Button("Done") { dismiss() } | |
| 44 | + .keyboardShortcut(.defaultAction) | |
| 45 | + } | |
| 46 | + .padding(24) | |
| 47 | + .frame(width: 380) | |
| 48 | + } | |
| 49 | +} | |
added
Sources/OSVaultKit/Views/Send/SendView.swift
+324 −0
@@ -0,0 +1,324 @@ | ||
| 1 | +// | |
| 2 | +// SendView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Send flow: token + recipient + amount → prepare (gas preview) → | |
| 13 | +/// confirmation screen showing recipient, amount, network, gas and total → | |
| 14 | +/// password re-entry unlocks the vault, signs, broadcasts, tracks the receipt. | |
| 15 | +struct SendView: View { | |
| 16 | + @EnvironmentObject var app: AppState | |
| 17 | + @Environment(\.dismiss) private var dismiss | |
| 18 | + | |
| 19 | + enum Stage { | |
| 20 | + case form | |
| 21 | + case preparing | |
| 22 | + case confirm(TransactionService.PreparedTransfer) | |
| 23 | + case sending | |
| 24 | + case sent(hash: String) | |
| 25 | + } | |
| 26 | + | |
| 27 | + @State private var stage: Stage = .form | |
| 28 | + @State private var asset: Asset = .token(.usdc) | |
| 29 | + @State private var recipientInput = "" | |
| 30 | + @State private var amountInput = "" | |
| 31 | + @State private var password = "" | |
| 32 | + @State private var errorMessage: String? | |
| 33 | + | |
| 34 | + var body: some View { | |
| 35 | + VStack(alignment: .leading, spacing: 16) { | |
| 36 | + HStack { | |
| 37 | + Text("Send").font(.title2.bold()) | |
| 38 | + Spacer() | |
| 39 | + NetworkBadge(network: app.network) | |
| 40 | + } | |
| 41 | + content | |
| 42 | + } | |
| 43 | + .padding(24) | |
| 44 | + .frame(width: 460) | |
| 45 | + } | |
| 46 | + | |
| 47 | + @ViewBuilder | |
| 48 | + private var content: some View { | |
| 49 | + switch stage { | |
| 50 | + case .form, .preparing: | |
| 51 | + form | |
| 52 | + case .confirm(let prepared): | |
| 53 | + confirmView(prepared) | |
| 54 | + case .sending: | |
| 55 | + HStack { | |
| 56 | + ProgressView().controlSize(.small) | |
| 57 | + Text("Signing and broadcasting…") | |
| 58 | + } | |
| 59 | + .frame(maxWidth: .infinity, alignment: .center) | |
| 60 | + .padding(.vertical, 30) | |
| 61 | + case .sent(let hash): | |
| 62 | + sentView(hash) | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + // MARK: - Form | |
| 67 | + | |
| 68 | + private var recipientVerdict: AddressValidator.Verdict { | |
| 69 | + AddressValidator.validate(recipientInput) | |
| 70 | + } | |
| 71 | + | |
| 72 | + private var form: some View { | |
| 73 | + VStack(alignment: .leading, spacing: 14) { | |
| 74 | + Picker("Asset", selection: $asset) { | |
| 75 | + ForEach(Asset.available(on: app.network)) { candidate in | |
| 76 | + Text("\(candidate.symbol(on: app.network)) — \(candidate.name(on: app.network))") | |
| 77 | + .tag(candidate) | |
| 78 | + } | |
| 79 | + } | |
| 80 | + | |
| 81 | + VStack(alignment: .leading, spacing: 4) { | |
| 82 | + TextField("Recipient address (0x…)", text: $recipientInput) | |
| 83 | + .textFieldStyle(.roundedBorder) | |
| 84 | + .font(.body.monospaced()) | |
| 85 | + .autocorrectionDisabled() | |
| 86 | + switch recipientVerdict { | |
| 87 | + case .valid: | |
| 88 | + Label("Checksum valid", systemImage: "checkmark.circle") | |
| 89 | + .font(.caption).foregroundStyle(.green) | |
| 90 | + case .validNoChecksum: | |
| 91 | + Label("Address has no checksum (all one case). Double-check it before sending.", | |
| 92 | + systemImage: "exclamationmark.triangle") | |
| 93 | + .font(.caption).foregroundStyle(.orange) | |
| 94 | + case .invalid: | |
| 95 | + if !recipientInput.isEmpty { | |
| 96 | + Label("Not a valid address", systemImage: "xmark.circle") | |
| 97 | + .font(.caption).foregroundStyle(.red) | |
| 98 | + } | |
| 99 | + } | |
| 100 | + } | |
| 101 | + | |
| 102 | + VStack(alignment: .leading, spacing: 4) { | |
| 103 | + HStack { | |
| 104 | + TextField("Amount", text: $amountInput) | |
| 105 | + .textFieldStyle(.roundedBorder) | |
| 106 | + .font(.body.monospaced()) | |
| 107 | + Text(asset.symbol(on: app.network)).foregroundStyle(.secondary) | |
| 108 | + Button("Max") { | |
| 109 | + amountInput = TokenAmount.format(assetBalance, decimals: asset.decimals) | |
| 110 | + } | |
| 111 | + .controlSize(.small) | |
| 112 | + } | |
| 113 | + Text("Balance: \(TokenAmount.format(assetBalance, decimals: asset.decimals)) \(asset.symbol(on: app.network))") | |
| 114 | + .font(.caption) | |
| 115 | + .foregroundStyle(.secondary) | |
| 116 | + } | |
| 117 | + | |
| 118 | + if let errorMessage { | |
| 119 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 120 | + } | |
| 121 | + | |
| 122 | + HStack { | |
| 123 | + Button("Cancel") { dismiss() } | |
| 124 | + Spacer() | |
| 125 | + if case .preparing = stage { | |
| 126 | + ProgressView().controlSize(.small) | |
| 127 | + } | |
| 128 | + Button("Review") { prepare() } | |
| 129 | + .buttonStyle(.borderedProminent) | |
| 130 | + .disabled(!formValid || isPreparing) | |
| 131 | + } | |
| 132 | + } | |
| 133 | + .onAppear { resetAssetIfUnavailable() } | |
| 134 | + .onChange(of: app.network) { _, _ in resetAssetIfUnavailable(force: true) } | |
| 135 | + } | |
| 136 | + | |
| 137 | + private func resetAssetIfUnavailable(force: Bool = false) { | |
| 138 | + let available = Asset.available(on: app.network) | |
| 139 | + if force || !available.contains(asset) { | |
| 140 | + asset = available.first ?? .native | |
| 141 | + } | |
| 142 | + } | |
| 143 | + | |
| 144 | + private var assetBalance: BigUInt { | |
| 145 | + switch asset { | |
| 146 | + case .native: return app.balances.ethWei | |
| 147 | + case .token(let token): return app.balances.tokenUnits[token.symbol] ?? 0 | |
| 148 | + } | |
| 149 | + } | |
| 150 | + | |
| 151 | + private var isPreparing: Bool { | |
| 152 | + if case .preparing = stage { return true } | |
| 153 | + return false | |
| 154 | + } | |
| 155 | + | |
| 156 | + private var formValid: Bool { | |
| 157 | + recipientVerdict != .invalid | |
| 158 | + && TokenAmount.parse(amountInput, decimals: asset.decimals).map { $0 > 0 } == true | |
| 159 | + } | |
| 160 | + | |
| 161 | + private func prepare() { | |
| 162 | + guard let from = app.address, | |
| 163 | + let amount = TokenAmount.parse(amountInput, decimals: asset.decimals) else { return } | |
| 164 | + let checksummedRecipient: String | |
| 165 | + switch recipientVerdict { | |
| 166 | + case .valid(let c), .validNoChecksum(let c): checksummedRecipient = c | |
| 167 | + case .invalid: return | |
| 168 | + } | |
| 169 | + errorMessage = nil | |
| 170 | + stage = .preparing | |
| 171 | + let network = app.network | |
| 172 | + let rpc = app.rpc() | |
| 173 | + let balances = app.balances | |
| 174 | + let selectedAsset = asset | |
| 175 | + Task { | |
| 176 | + do { | |
| 177 | + let prepared = try await TransactionService.prepare( | |
| 178 | + asset: selectedAsset, network: network, from: from, | |
| 179 | + recipient: checksummedRecipient, amountUnits: amount, | |
| 180 | + rpc: rpc, balances: balances | |
| 181 | + ) | |
| 182 | + stage = .confirm(prepared) | |
| 183 | + } catch { | |
| 184 | + errorMessage = error.localizedDescription | |
| 185 | + stage = .form | |
| 186 | + } | |
| 187 | + } | |
| 188 | + } | |
| 189 | + | |
| 190 | + // MARK: - Confirm | |
| 191 | + | |
| 192 | + private func confirmView(_ prepared: TransactionService.PreparedTransfer) -> some View { | |
| 193 | + VStack(alignment: .leading, spacing: 14) { | |
| 194 | + Text("Confirm transaction").font(.headline) | |
| 195 | + | |
| 196 | + Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 8) { | |
| 197 | + GridRow { | |
| 198 | + Text("Recipient").foregroundStyle(.secondary) | |
| 199 | + Text(prepared.recipient).font(.callout.monospaced()).textSelection(.enabled) | |
| 200 | + } | |
| 201 | + GridRow { | |
| 202 | + Text("Amount").foregroundStyle(.secondary) | |
| 203 | + Text("\(TokenAmount.format(prepared.amountUnits, decimals: prepared.asset.decimals)) \(prepared.asset.symbol(on: prepared.network))") | |
| 204 | + .fontWeight(.semibold) | |
| 205 | + } | |
| 206 | + GridRow { | |
| 207 | + Text("Network").foregroundStyle(.secondary) | |
| 208 | + Text("\(prepared.network.config.displayName) (chain \(String(prepared.network.config.chainID)))") | |
| 209 | + } | |
| 210 | + GridRow { | |
| 211 | + Text("Max gas").foregroundStyle(.secondary) | |
| 212 | + Text("\(TokenAmount.formatWei(prepared.maxGasCostWei)) \(prepared.network.config.nativeSymbol)" + (prepared.l1DataFee > 0 ? " (incl. L1 data fee)" : "")) | |
| 213 | + } | |
| 214 | + GridRow { | |
| 215 | + Text("Total").foregroundStyle(.secondary) | |
| 216 | + totalText(prepared) | |
| 217 | + } | |
| 218 | + } | |
| 219 | + .font(.callout) | |
| 220 | + | |
| 221 | + Divider() | |
| 222 | + Text("Enter your vault password to sign.") | |
| 223 | + .font(.callout) | |
| 224 | + .foregroundStyle(.secondary) | |
| 225 | + SecureField("Vault password", text: $password) | |
| 226 | + .textFieldStyle(.roundedBorder) | |
| 227 | + if let errorMessage { | |
| 228 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 229 | + } | |
| 230 | + HStack { | |
| 231 | + Button("Back") { | |
| 232 | + password = "" | |
| 233 | + errorMessage = nil | |
| 234 | + stage = .form | |
| 235 | + } | |
| 236 | + Spacer() | |
| 237 | + Button("Sign & send") { send(prepared) } | |
| 238 | + .buttonStyle(.borderedProminent) | |
| 239 | + .disabled(password.isEmpty) | |
| 240 | + } | |
| 241 | + } | |
| 242 | + } | |
| 243 | + | |
| 244 | + private func totalText(_ prepared: TransactionService.PreparedTransfer) -> Text { | |
| 245 | + let native = prepared.network.config.nativeSymbol | |
| 246 | + switch prepared.asset { | |
| 247 | + case .native: | |
| 248 | + let total = prepared.amountUnits + prepared.maxGasCostWei | |
| 249 | + return Text("≤ \(TokenAmount.formatWei(total)) \(native) (amount + max gas)") | |
| 250 | + case .token(let token): | |
| 251 | + return Text("\(TokenAmount.format(prepared.amountUnits, decimals: token.decimals)) \(token.symbol) + gas in \(native)") | |
| 252 | + } | |
| 253 | + } | |
| 254 | + | |
| 255 | + private func send(_ prepared: TransactionService.PreparedTransfer) { | |
| 256 | + errorMessage = nil | |
| 257 | + stage = .sending | |
| 258 | + let manager = app.keyManager | |
| 259 | + let candidate = password | |
| 260 | + let rpc = app.rpc() | |
| 261 | + Task { | |
| 262 | + do { | |
| 263 | + // Unlock off the main thread (slow KDF), sign, discard the key. | |
| 264 | + let wallet = try await Task.detached { | |
| 265 | + try manager.unlock(password: candidate) | |
| 266 | + }.value | |
| 267 | + let hash = try await TransactionService.send(prepared, privateKey: wallet.privateKey, rpc: rpc) | |
| 268 | + password = "" | |
| 269 | + app.recordSend(TransactionRecord( | |
| 270 | + hash: hash, asset: prepared.asset, amountUnits: prepared.amountUnits, | |
| 271 | + recipient: prepared.recipient, network: prepared.network, status: .pending | |
| 272 | + )) | |
| 273 | + stage = .sent(hash: hash) | |
| 274 | + trackReceipt(hash: hash, rpc: rpc) | |
| 275 | + } catch { | |
| 276 | + errorMessage = error.localizedDescription | |
| 277 | + stage = .confirm(prepared) | |
| 278 | + } | |
| 279 | + } | |
| 280 | + } | |
| 281 | + | |
| 282 | + private func trackReceipt(hash: String, rpc: RPCService) { | |
| 283 | + Task { | |
| 284 | + let outcome = await TransactionService.waitForReceipt(hash: hash, rpc: rpc) | |
| 285 | + switch outcome { | |
| 286 | + case .confirmed: | |
| 287 | + app.updateRecord(hash: hash, status: .confirmed) | |
| 288 | + case .failed: | |
| 289 | + app.updateRecord(hash: hash, status: .failed) | |
| 290 | + case .timedOut: | |
| 291 | + break // stays pending; explorer link tells the full story | |
| 292 | + } | |
| 293 | + await app.refreshBalances() | |
| 294 | + } | |
| 295 | + } | |
| 296 | + | |
| 297 | + // MARK: - Sent | |
| 298 | + | |
| 299 | + private func sentView(_ hash: String) -> some View { | |
| 300 | + VStack(spacing: 14) { | |
| 301 | + Image(systemName: "paperplane.circle.fill") | |
| 302 | + .font(.system(size: 40)) | |
| 303 | + .foregroundStyle(.green) | |
| 304 | + Text("Transaction broadcast").font(.headline) | |
| 305 | + Text(hash) | |
| 306 | + .font(.caption.monospaced()) | |
| 307 | + .textSelection(.enabled) | |
| 308 | + .lineLimit(1) | |
| 309 | + .truncationMode(.middle) | |
| 310 | + Text("Status will update in Activity once the network confirms it (usually a few seconds on Base).") | |
| 311 | + .font(.callout) | |
| 312 | + .foregroundStyle(.secondary) | |
| 313 | + .multilineTextAlignment(.center) | |
| 314 | + HStack { | |
| 315 | + Link("View on BaseScan", destination: app.network.explorerTxURL(hash)) | |
| 316 | + Spacer() | |
| 317 | + Button("Done") { dismiss() } | |
| 318 | + .buttonStyle(.borderedProminent) | |
| 319 | + .keyboardShortcut(.defaultAction) | |
| 320 | + } | |
| 321 | + } | |
| 322 | + .frame(maxWidth: .infinity) | |
| 323 | + } | |
| 324 | +} | |
added
Sources/OSVaultKit/Views/Settings/SettingsView.swift
+201 −0
@@ -0,0 +1,201 @@ | ||
| 1 | +// | |
| 2 | +// SettingsView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | + | |
| 11 | +struct SettingsView: View { | |
| 12 | + @EnvironmentObject var app: AppState | |
| 13 | + @Environment(\.dismiss) private var dismiss | |
| 14 | + | |
| 15 | + @State private var rpcOverride = "" | |
| 16 | + @State private var exportPassword = "" | |
| 17 | + @State private var exportedMnemonic: String? | |
| 18 | + @State private var exportError: String? | |
| 19 | + @State private var deleteConfirmation = "" | |
| 20 | + @State private var deleteError: String? | |
| 21 | + | |
| 22 | + var body: some View { | |
| 23 | + VStack(alignment: .leading, spacing: 0) { | |
| 24 | + HStack { | |
| 25 | + Text("Settings").font(.title2.bold()) | |
| 26 | + Spacer() | |
| 27 | + Button("Done") { dismiss() } | |
| 28 | + .keyboardShortcut(.defaultAction) | |
| 29 | + } | |
| 30 | + .padding(.bottom, 12) | |
| 31 | + | |
| 32 | + ScrollView { | |
| 33 | + VStack(alignment: .leading, spacing: 20) { | |
| 34 | + networkSection | |
| 35 | + Divider() | |
| 36 | + pricesSection | |
| 37 | + Divider() | |
| 38 | + rpcSection | |
| 39 | + Divider() | |
| 40 | + exportSection | |
| 41 | + Divider() | |
| 42 | + deleteSection | |
| 43 | + } | |
| 44 | + .padding(.vertical, 4) | |
| 45 | + } | |
| 46 | + } | |
| 47 | + .padding(24) | |
| 48 | + .frame(width: 480, height: 560) | |
| 49 | + .onAppear { | |
| 50 | + rpcOverride = UserDefaults.standard.string(forKey: app.network.rpcOverrideKey) ?? "" | |
| 51 | + } | |
| 52 | + } | |
| 53 | + | |
| 54 | + // MARK: - Network | |
| 55 | + | |
| 56 | + private var networkSection: some View { | |
| 57 | + VStack(alignment: .leading, spacing: 8) { | |
| 58 | + Text("Network").font(.headline) | |
| 59 | + Picker("Active network", selection: $app.network) { | |
| 60 | + ForEach(Network.allCases) { network in | |
| 61 | + Text(network.config.displayName + (network.config.isTestnet ? " (testnet)" : "")) | |
| 62 | + .tag(network) | |
| 63 | + } | |
| 64 | + } | |
| 65 | + .pickerStyle(.menu) | |
| 66 | + if !app.network.config.isTestnet { | |
| 67 | + Label("Mainnet moves real funds. Double-check every send.", | |
| 68 | + systemImage: "exclamationmark.triangle.fill") | |
| 69 | + .font(.callout) | |
| 70 | + .foregroundStyle(.orange) | |
| 71 | + } | |
| 72 | + } | |
| 73 | + .onChange(of: app.network) { _, newNetwork in | |
| 74 | + rpcOverride = UserDefaults.standard.string(forKey: newNetwork.rpcOverrideKey) ?? "" | |
| 75 | + } | |
| 76 | + } | |
| 77 | + | |
| 78 | + // MARK: - Prices | |
| 79 | + | |
| 80 | + private var pricesSection: some View { | |
| 81 | + VStack(alignment: .leading, spacing: 8) { | |
| 82 | + Text("Fiat values").font(.headline) | |
| 83 | + Toggle("Show fiat values (fetches prices from CoinGecko, keyless)", isOn: $app.pricesEnabled) | |
| 84 | + if app.pricesEnabled { | |
| 85 | + Picker("Currency", selection: $app.fiatCurrency) { | |
| 86 | + ForEach(PriceService.fiatOptions, id: \.self) { Text($0).tag($0) } | |
| 87 | + } | |
| 88 | + .pickerStyle(.segmented) | |
| 89 | + .frame(maxWidth: 260) | |
| 90 | + } | |
| 91 | + Text("Balances are always exact on-chain amounts; fiat values are display estimates. Turning this off removes the only non-blockchain network call.") | |
| 92 | + .font(.caption) | |
| 93 | + .foregroundStyle(.secondary) | |
| 94 | + } | |
| 95 | + } | |
| 96 | + | |
| 97 | + // MARK: - RPC | |
| 98 | + | |
| 99 | + private var rpcSection: some View { | |
| 100 | + VStack(alignment: .leading, spacing: 8) { | |
| 101 | + Text("Custom RPC for \(app.network.config.displayName)").font(.headline) | |
| 102 | + Text("Leave empty to use the built-in keyless endpoints (\(app.network.config.rpcs.map(\.host!).joined(separator: ", "))) with automatic failover. A dedicated Alchemy/QuickNode URL is more reliable; no key is ever required to run OS Vault.") | |
| 103 | + .font(.caption) | |
| 104 | + .foregroundStyle(.secondary) | |
| 105 | + HStack { | |
| 106 | + TextField("https://…", text: $rpcOverride) | |
| 107 | + .textFieldStyle(.roundedBorder) | |
| 108 | + .autocorrectionDisabled() | |
| 109 | + Button("Save") { | |
| 110 | + let trimmed = rpcOverride.trimmingCharacters(in: .whitespacesAndNewlines) | |
| 111 | + if trimmed.isEmpty { | |
| 112 | + UserDefaults.standard.removeObject(forKey: app.network.rpcOverrideKey) | |
| 113 | + } else { | |
| 114 | + UserDefaults.standard.set(trimmed, forKey: app.network.rpcOverrideKey) | |
| 115 | + } | |
| 116 | + Task { await app.refreshBalances() } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + } | |
| 120 | + } | |
| 121 | + | |
| 122 | + // MARK: - Export seed | |
| 123 | + | |
| 124 | + private var exportSection: some View { | |
| 125 | + VStack(alignment: .leading, spacing: 8) { | |
| 126 | + Text("Recovery phrase").font(.headline) | |
| 127 | + if let exportedMnemonic { | |
| 128 | + Text(exportedMnemonic) | |
| 129 | + .font(.callout.monospaced()) | |
| 130 | + .textSelection(.enabled) | |
| 131 | + .padding(10) | |
| 132 | + .frame(maxWidth: .infinity, alignment: .leading) | |
| 133 | + .background(Color.orange.opacity(0.12)) | |
| 134 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 135 | + Button("Hide") { | |
| 136 | + self.exportedMnemonic = nil | |
| 137 | + exportPassword = "" | |
| 138 | + } | |
| 139 | + } else { | |
| 140 | + Text("Reveals the 12 words that control your funds. Make sure nobody can see your screen.") | |
| 141 | + .font(.caption) | |
| 142 | + .foregroundStyle(.secondary) | |
| 143 | + HStack { | |
| 144 | + SecureField("Vault password", text: $exportPassword) | |
| 145 | + .textFieldStyle(.roundedBorder) | |
| 146 | + Button("Reveal") { export() } | |
| 147 | + .disabled(exportPassword.isEmpty) | |
| 148 | + } | |
| 149 | + if let exportError { | |
| 150 | + Text(exportError).foregroundStyle(.red).font(.callout) | |
| 151 | + } | |
| 152 | + } | |
| 153 | + } | |
| 154 | + } | |
| 155 | + | |
| 156 | + private func export() { | |
| 157 | + exportError = nil | |
| 158 | + let manager = app.keyManager | |
| 159 | + let candidate = exportPassword | |
| 160 | + Task { | |
| 161 | + let result = await Task.detached { | |
| 162 | + Result { try manager.exportMnemonic(password: candidate) } | |
| 163 | + }.value | |
| 164 | + switch result { | |
| 165 | + case .success(let mnemonic): exportedMnemonic = mnemonic | |
| 166 | + case .failure(let error): exportError = error.localizedDescription | |
| 167 | + } | |
| 168 | + } | |
| 169 | + } | |
| 170 | + | |
| 171 | + // MARK: - Delete | |
| 172 | + | |
| 173 | + private var deleteSection: some View { | |
| 174 | + VStack(alignment: .leading, spacing: 8) { | |
| 175 | + Text("Danger zone").font(.headline).foregroundStyle(.red) | |
| 176 | + Text("Deletes the encrypted vault from this Mac. Without your written recovery phrase, the funds are unrecoverable. Type DELETE to confirm.") | |
| 177 | + .font(.caption) | |
| 178 | + .foregroundStyle(.secondary) | |
| 179 | + HStack { | |
| 180 | + TextField("Type DELETE", text: $deleteConfirmation) | |
| 181 | + .textFieldStyle(.roundedBorder) | |
| 182 | + Button("Delete wallet", role: .destructive) { | |
| 183 | + guard deleteConfirmation == "DELETE" else { | |
| 184 | + deleteError = "Type DELETE (all caps) to confirm." | |
| 185 | + return | |
| 186 | + } | |
| 187 | + do { | |
| 188 | + try app.keyManager.deleteVault() | |
| 189 | + dismiss() | |
| 190 | + app.walletDeleted() | |
| 191 | + } catch { | |
| 192 | + deleteError = error.localizedDescription | |
| 193 | + } | |
| 194 | + } | |
| 195 | + } | |
| 196 | + if let deleteError { | |
| 197 | + Text(deleteError).foregroundStyle(.red).font(.callout) | |
| 198 | + } | |
| 199 | + } | |
| 200 | + } | |
| 201 | +} | |
added
Sources/OSVaultKit/Views/Shared.swift
+51 −0
@@ -0,0 +1,51 @@ | ||
| 1 | +// | |
| 2 | +// Shared.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | + | |
| 11 | +/// Prominent badge so the user always knows which chain they are on. | |
| 12 | +struct NetworkBadge: View { | |
| 13 | + let network: Network | |
| 14 | + | |
| 15 | + var body: some View { | |
| 16 | + Text(network.config.isTestnet ? "TESTNET · \(network.config.displayName)" : network.config.displayName) | |
| 17 | + .font(.caption.weight(.bold)) | |
| 18 | + .padding(.horizontal, 10) | |
| 19 | + .padding(.vertical, 4) | |
| 20 | + .background(network.config.isTestnet ? Color.orange.opacity(0.25) : Color.blue.opacity(0.18)) | |
| 21 | + .foregroundStyle(network.config.isTestnet ? Color.orange : Color.blue) | |
| 22 | + .clipShape(Capsule()) | |
| 23 | + } | |
| 24 | +} | |
| 25 | + | |
| 26 | +extension String { | |
| 27 | + /// "0x9858…da94" for tight UI spots. | |
| 28 | + var shortAddress: String { | |
| 29 | + guard count == 42 else { return self } | |
| 30 | + return "\(prefix(6))…\(suffix(4))" | |
| 31 | + } | |
| 32 | +} | |
| 33 | + | |
| 34 | +struct CopyButton: View { | |
| 35 | + let text: String | |
| 36 | + @State private var copied = false | |
| 37 | + | |
| 38 | + var body: some View { | |
| 39 | + Button { | |
| 40 | + NSPasteboard.general.clearContents() | |
| 41 | + NSPasteboard.general.setString(text, forType: .string) | |
| 42 | + copied = true | |
| 43 | + Task { | |
| 44 | + try? await Task.sleep(for: .seconds(1.5)) | |
| 45 | + copied = false | |
| 46 | + } | |
| 47 | + } label: { | |
| 48 | + Label(copied ? "Copied" : "Copy", systemImage: copied ? "checkmark" : "doc.on.doc") | |
| 49 | + } | |
| 50 | + } | |
| 51 | +} | |
added
Sources/OSVaultKit/Views/Solana/SolanaView.swift
+337 −0
@@ -0,0 +1,337 @@ | ||
| 1 | +// | |
| 2 | +// SolanaView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Solana panel: SOL + USDC balances, receive, send (with ATA-rent warning | |
| 13 | +/// when the recipient has no USDC account yet), devnet/mainnet switch. | |
| 14 | +/// Sends follow the vault flow: password → derive keypair → sign → discard. | |
| 15 | +struct SolanaView: View { | |
| 16 | + @EnvironmentObject var app: AppState | |
| 17 | + @Environment(\.dismiss) private var dismiss | |
| 18 | + | |
| 19 | + enum Mode { case overview, receive, send } | |
| 20 | + @State private var mode: Mode = .overview | |
| 21 | + | |
| 22 | + @State private var sendUSDC = true | |
| 23 | + @State private var recipient = "" | |
| 24 | + @State private var amountInput = "" | |
| 25 | + @State private var prepared: SolanaService.PreparedSOLSend? | |
| 26 | + @State private var password = "" | |
| 27 | + @State private var sending = false | |
| 28 | + @State private var sentSignature: String? | |
| 29 | + @State private var errorMessage: String? | |
| 30 | + | |
| 31 | + var body: some View { | |
| 32 | + VStack(alignment: .leading, spacing: 16) { | |
| 33 | + header | |
| 34 | + switch mode { | |
| 35 | + case .overview: overview | |
| 36 | + case .receive: receive | |
| 37 | + case .send: send | |
| 38 | + } | |
| 39 | + } | |
| 40 | + .padding(24) | |
| 41 | + .frame(width: 470) | |
| 42 | + } | |
| 43 | + | |
| 44 | + private var header: some View { | |
| 45 | + HStack { | |
| 46 | + Text("Solana").font(.title2.bold()) | |
| 47 | + Spacer() | |
| 48 | + Text(app.solNetwork.isTestnet ? "DEVNET · test" : "MAINNET") | |
| 49 | + .font(.caption.weight(.bold)) | |
| 50 | + .padding(.horizontal, 10).padding(.vertical, 4) | |
| 51 | + .background(app.solNetwork.isTestnet ? Color.orange.opacity(0.25) : Color.purple.opacity(0.25)) | |
| 52 | + .foregroundStyle(app.solNetwork.isTestnet ? Color.orange : Color.purple) | |
| 53 | + .clipShape(Capsule()) | |
| 54 | + Button("Done") { dismiss() } | |
| 55 | + } | |
| 56 | + } | |
| 57 | + | |
| 58 | + // MARK: - Overview | |
| 59 | + | |
| 60 | + private var overview: some View { | |
| 61 | + VStack(alignment: .leading, spacing: 14) { | |
| 62 | + VStack(alignment: .leading, spacing: 10) { | |
| 63 | + HStack(alignment: .firstTextBaseline) { | |
| 64 | + Text("USDC").font(.headline) | |
| 65 | + Spacer() | |
| 66 | + VStack(alignment: .trailing, spacing: 2) { | |
| 67 | + Text(TokenAmount.format(BigUInt(app.solBalances?.usdcUnits ?? 0), decimals: 6)) | |
| 68 | + .font(.system(size: 26, weight: .bold, design: .rounded)) | |
| 69 | + .monospacedDigit() | |
| 70 | + if let fiat = fiatLine(units: app.solBalances?.usdcUnits ?? 0, decimals: 6, symbol: "USDC") { | |
| 71 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 72 | + } | |
| 73 | + } | |
| 74 | + } | |
| 75 | + Divider() | |
| 76 | + HStack { | |
| 77 | + Text("SOL (fees)").font(.subheadline).foregroundStyle(.secondary) | |
| 78 | + Spacer() | |
| 79 | + VStack(alignment: .trailing, spacing: 2) { | |
| 80 | + Text(SolanaService.formatSOL(app.solBalances?.lamports ?? 0) + " SOL") | |
| 81 | + .font(.subheadline.monospaced()) | |
| 82 | + .foregroundStyle(.secondary) | |
| 83 | + if let fiat = fiatLine(units: app.solBalances?.lamports ?? 0, decimals: 9, symbol: "SOL") { | |
| 84 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 85 | + } | |
| 86 | + } | |
| 87 | + } | |
| 88 | + if let error = app.solError { | |
| 89 | + Label(error, systemImage: "wifi.exclamationmark") | |
| 90 | + .font(.caption).foregroundStyle(.orange) | |
| 91 | + } | |
| 92 | + } | |
| 93 | + .padding(14) | |
| 94 | + .background(.quaternary.opacity(0.4)) | |
| 95 | + .clipShape(RoundedRectangle(cornerRadius: 10)) | |
| 96 | + | |
| 97 | + HStack(spacing: 12) { | |
| 98 | + Button { | |
| 99 | + mode = .send | |
| 100 | + } label: { | |
| 101 | + Label("Send", systemImage: "arrow.up.circle.fill").frame(maxWidth: .infinity) | |
| 102 | + } | |
| 103 | + .buttonStyle(.borderedProminent) | |
| 104 | + Button { | |
| 105 | + mode = .receive | |
| 106 | + } label: { | |
| 107 | + Label("Receive", systemImage: "arrow.down.circle").frame(maxWidth: .infinity) | |
| 108 | + } | |
| 109 | + Button { | |
| 110 | + Task { await app.refreshSolana() } | |
| 111 | + } label: { | |
| 112 | + Image(systemName: "arrow.clockwise") | |
| 113 | + } | |
| 114 | + .help("Refresh") | |
| 115 | + } | |
| 116 | + | |
| 117 | + Text("ed25519 at m/44'/501'/0'/0' from your existing recovery phrase (Phantom-compatible). Fees are paid in SOL.") | |
| 118 | + .font(.caption) | |
| 119 | + .foregroundStyle(.secondary) | |
| 120 | + | |
| 121 | + Picker("Network", selection: Binding( | |
| 122 | + get: { app.solNetwork }, | |
| 123 | + set: { newValue in Task { await app.switchSolanaNetwork(to: newValue) } } | |
| 124 | + )) { | |
| 125 | + ForEach(SolanaService.SOLNetwork.allCases, id: \.self) { network in | |
| 126 | + Text(network.displayName).tag(network) | |
| 127 | + } | |
| 128 | + } | |
| 129 | + .pickerStyle(.segmented) | |
| 130 | + } | |
| 131 | + } | |
| 132 | + | |
| 133 | + private func fiatLine(units: UInt64, decimals: Int, symbol: String) -> String? { | |
| 134 | + guard app.pricesEnabled, units > 0, let price = app.fiatPrices[symbol] else { return nil } | |
| 135 | + let value = PriceService.fiatValue(units: BigUInt(units), decimals: decimals, price: price) | |
| 136 | + return "≈ " + PriceService.formatFiat(value, currency: app.fiatCurrency) | |
| 137 | + } | |
| 138 | + | |
| 139 | + // MARK: - Receive | |
| 140 | + | |
| 141 | + private var receive: some View { | |
| 142 | + VStack(spacing: 14) { | |
| 143 | + if let address = app.solAddress { | |
| 144 | + if let qr = QRCode.image(for: address) { | |
| 145 | + Image(nsImage: qr) | |
| 146 | + .interpolation(.none) | |
| 147 | + .resizable() | |
| 148 | + .frame(width: 200, height: 200) | |
| 149 | + .background(.white) | |
| 150 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 151 | + } | |
| 152 | + Text(address) | |
| 153 | + .font(.callout.monospaced()) | |
| 154 | + .textSelection(.enabled) | |
| 155 | + .padding(8) | |
| 156 | + .background(.quaternary.opacity(0.4)) | |
| 157 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 158 | + CopyButton(text: address) | |
| 159 | + Text("One address for SOL and every SPL token on \(app.solNetwork.displayName).") | |
| 160 | + .font(.caption).foregroundStyle(.secondary) | |
| 161 | + } | |
| 162 | + Button("Back") { mode = .overview } | |
| 163 | + } | |
| 164 | + .frame(maxWidth: .infinity) | |
| 165 | + } | |
| 166 | + | |
| 167 | + // MARK: - Send | |
| 168 | + | |
| 169 | + private var send: some View { | |
| 170 | + VStack(alignment: .leading, spacing: 12) { | |
| 171 | + if let signature = sentSignature { | |
| 172 | + sentView(signature) | |
| 173 | + } else if let prepared { | |
| 174 | + confirmView(prepared) | |
| 175 | + } else { | |
| 176 | + sendForm | |
| 177 | + } | |
| 178 | + } | |
| 179 | + } | |
| 180 | + | |
| 181 | + private var sendForm: some View { | |
| 182 | + VStack(alignment: .leading, spacing: 12) { | |
| 183 | + Picker("Asset", selection: $sendUSDC) { | |
| 184 | + Text("USDC").tag(true) | |
| 185 | + Text("SOL").tag(false) | |
| 186 | + } | |
| 187 | + .pickerStyle(.segmented) | |
| 188 | + TextField("Recipient (Solana address)", text: $recipient) | |
| 189 | + .textFieldStyle(.roundedBorder) | |
| 190 | + .font(.body.monospaced()) | |
| 191 | + .autocorrectionDisabled() | |
| 192 | + if !recipient.isEmpty && !SolanaService.validate(address: recipient) { | |
| 193 | + Label("Not a valid Solana address", systemImage: "xmark.circle") | |
| 194 | + .font(.caption).foregroundStyle(.red) | |
| 195 | + } | |
| 196 | + HStack { | |
| 197 | + TextField("Amount", text: $amountInput) | |
| 198 | + .textFieldStyle(.roundedBorder) | |
| 199 | + .font(.body.monospaced()) | |
| 200 | + Text(sendUSDC ? "USDC" : "SOL").foregroundStyle(.secondary) | |
| 201 | + } | |
| 202 | + Text(sendUSDC | |
| 203 | + ? "Balance: \(TokenAmount.format(BigUInt(app.solBalances?.usdcUnits ?? 0), decimals: 6)) USDC" | |
| 204 | + : "Balance: \(SolanaService.formatSOL(app.solBalances?.lamports ?? 0)) SOL") | |
| 205 | + .font(.caption).foregroundStyle(.secondary) | |
| 206 | + if let errorMessage { | |
| 207 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 208 | + } | |
| 209 | + HStack { | |
| 210 | + Button("Back") { mode = .overview; errorMessage = nil } | |
| 211 | + Spacer() | |
| 212 | + Button("Review") { estimate() } | |
| 213 | + .buttonStyle(.borderedProminent) | |
| 214 | + .disabled(!formValid) | |
| 215 | + } | |
| 216 | + } | |
| 217 | + } | |
| 218 | + | |
| 219 | + private var parsedAmount: UInt64? { | |
| 220 | + sendUSDC ? SolanaService.parseUSDC(amountInput) : SolanaService.parseSOL(amountInput) | |
| 221 | + } | |
| 222 | + | |
| 223 | + private var formValid: Bool { | |
| 224 | + SolanaService.validate(address: recipient) && (parsedAmount ?? 0) > 0 | |
| 225 | + } | |
| 226 | + | |
| 227 | + private func estimate() { | |
| 228 | + guard let amount = parsedAmount else { return } | |
| 229 | + errorMessage = nil | |
| 230 | + let to = recipient.trimmingCharacters(in: .whitespacesAndNewlines) | |
| 231 | + let usdc = sendUSDC | |
| 232 | + Task { | |
| 233 | + do { | |
| 234 | + prepared = try await app.solanaService.estimateSend( | |
| 235 | + to: to, amountUnits: amount, isUSDC: usdc) | |
| 236 | + } catch { | |
| 237 | + errorMessage = error.localizedDescription | |
| 238 | + } | |
| 239 | + } | |
| 240 | + } | |
| 241 | + | |
| 242 | + private func confirmView(_ p: SolanaService.PreparedSOLSend) -> some View { | |
| 243 | + VStack(alignment: .leading, spacing: 12) { | |
| 244 | + Text("Confirm transaction").font(.headline) | |
| 245 | + Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 8) { | |
| 246 | + GridRow { | |
| 247 | + Text("Recipient").foregroundStyle(.secondary) | |
| 248 | + Text(p.recipient).font(.callout.monospaced()) | |
| 249 | + .textSelection(.enabled) | |
| 250 | + .lineLimit(1).truncationMode(.middle) | |
| 251 | + } | |
| 252 | + GridRow { | |
| 253 | + Text("Amount").foregroundStyle(.secondary) | |
| 254 | + Text(p.isUSDC | |
| 255 | + ? "\(TokenAmount.format(BigUInt(p.amountUnits), decimals: 6)) USDC" | |
| 256 | + : "\(SolanaService.formatSOL(p.amountUnits)) SOL") | |
| 257 | + .fontWeight(.semibold) | |
| 258 | + } | |
| 259 | + GridRow { | |
| 260 | + Text("Network").foregroundStyle(.secondary) | |
| 261 | + Text(p.network.displayName) | |
| 262 | + } | |
| 263 | + GridRow { | |
| 264 | + Text("Est. fee").foregroundStyle(.secondary) | |
| 265 | + Text("\(SolanaService.formatSOL(p.estimatedFeeLamports)) SOL") | |
| 266 | + } | |
| 267 | + } | |
| 268 | + .font(.callout) | |
| 269 | + if p.createsTokenAccount { | |
| 270 | + Label("The recipient has no USDC account yet — you fund its creation (~0.002 SOL rent, included in the fee above).", | |
| 271 | + systemImage: "info.circle") | |
| 272 | + .font(.caption) | |
| 273 | + .foregroundStyle(.orange) | |
| 274 | + } | |
| 275 | + Divider() | |
| 276 | + SecureField("Vault password to sign", text: $password) | |
| 277 | + .textFieldStyle(.roundedBorder) | |
| 278 | + if let errorMessage { | |
| 279 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 280 | + } | |
| 281 | + HStack { | |
| 282 | + Button("Back") { | |
| 283 | + prepared = nil | |
| 284 | + password = "" | |
| 285 | + } | |
| 286 | + Spacer() | |
| 287 | + if sending { ProgressView().controlSize(.small) } | |
| 288 | + Button("Sign & send") { broadcast(p) } | |
| 289 | + .buttonStyle(.borderedProminent) | |
| 290 | + .disabled(password.isEmpty || sending) | |
| 291 | + } | |
| 292 | + } | |
| 293 | + } | |
| 294 | + | |
| 295 | + private func broadcast(_ p: SolanaService.PreparedSOLSend) { | |
| 296 | + sending = true | |
| 297 | + errorMessage = nil | |
| 298 | + let candidate = password | |
| 299 | + let manager = app.keyManager | |
| 300 | + Task { | |
| 301 | + do { | |
| 302 | + let mnemonic = try await Task.detached { | |
| 303 | + try manager.unlock(password: candidate).mnemonic | |
| 304 | + }.value | |
| 305 | + let signature = try await app.solanaService.send(p, mnemonic: mnemonic) | |
| 306 | + password = "" | |
| 307 | + sentSignature = signature | |
| 308 | + await app.refreshSolana() | |
| 309 | + } catch { | |
| 310 | + errorMessage = error.localizedDescription | |
| 311 | + } | |
| 312 | + sending = false | |
| 313 | + } | |
| 314 | + } | |
| 315 | + | |
| 316 | + private func sentView(_ signature: String) -> some View { | |
| 317 | + VStack(spacing: 12) { | |
| 318 | + Image(systemName: "paperplane.circle.fill") | |
| 319 | + .font(.system(size: 38)).foregroundStyle(.green) | |
| 320 | + Text("Transaction sent").font(.headline) | |
| 321 | + Text(signature) | |
| 322 | + .font(.caption.monospaced()) | |
| 323 | + .textSelection(.enabled) | |
| 324 | + .lineLimit(1).truncationMode(.middle) | |
| 325 | + Link("View on Solana Explorer", destination: app.solNetwork.explorerTxURL(signature)) | |
| 326 | + Button("Done") { | |
| 327 | + sentSignature = nil | |
| 328 | + prepared = nil | |
| 329 | + recipient = "" | |
| 330 | + amountInput = "" | |
| 331 | + mode = .overview | |
| 332 | + } | |
| 333 | + .buttonStyle(.borderedProminent) | |
| 334 | + } | |
| 335 | + .frame(maxWidth: .infinity) | |
| 336 | + } | |
| 337 | +} | |
added
Sources/OSVaultKit/Views/TON/TONView.swift
+345 −0
@@ -0,0 +1,345 @@ | ||
| 1 | +// | |
| 2 | +// TONView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// TON panel: TON + USDT (jetton) balances, receive, send, testnet/mainnet | |
| 13 | +/// switch. USDT lives on mainnet only (no official testnet jetton). | |
| 14 | +struct TONView: View { | |
| 15 | + @EnvironmentObject var app: AppState | |
| 16 | + @Environment(\.dismiss) private var dismiss | |
| 17 | + | |
| 18 | + enum Mode { case overview, receive, send } | |
| 19 | + @State private var mode: Mode = .overview | |
| 20 | + | |
| 21 | + @State private var sendUSDT = false | |
| 22 | + @State private var recipient = "" | |
| 23 | + @State private var amountInput = "" | |
| 24 | + @State private var prepared: TONService.PreparedTONSend? | |
| 25 | + @State private var password = "" | |
| 26 | + @State private var busy = false | |
| 27 | + @State private var sentRef: String? | |
| 28 | + @State private var errorMessage: String? | |
| 29 | + | |
| 30 | + var body: some View { | |
| 31 | + VStack(alignment: .leading, spacing: 16) { | |
| 32 | + header | |
| 33 | + switch mode { | |
| 34 | + case .overview: overview | |
| 35 | + case .receive: receive | |
| 36 | + case .send: send | |
| 37 | + } | |
| 38 | + } | |
| 39 | + .padding(24) | |
| 40 | + .frame(width: 470) | |
| 41 | + } | |
| 42 | + | |
| 43 | + private var header: some View { | |
| 44 | + HStack { | |
| 45 | + Text("TON").font(.title2.bold()) | |
| 46 | + Spacer() | |
| 47 | + Text(app.tonNetwork.isTestnet ? "TESTNET" : "MAINNET") | |
| 48 | + .font(.caption.weight(.bold)) | |
| 49 | + .padding(.horizontal, 10).padding(.vertical, 4) | |
| 50 | + .background(app.tonNetwork.isTestnet ? Color.orange.opacity(0.25) : Color.cyan.opacity(0.2)) | |
| 51 | + .foregroundStyle(app.tonNetwork.isTestnet ? Color.orange : Color.cyan) | |
| 52 | + .clipShape(Capsule()) | |
| 53 | + Button("Done") { dismiss() } | |
| 54 | + } | |
| 55 | + } | |
| 56 | + | |
| 57 | + // MARK: - Overview | |
| 58 | + | |
| 59 | + private var overview: some View { | |
| 60 | + VStack(alignment: .leading, spacing: 14) { | |
| 61 | + VStack(alignment: .leading, spacing: 10) { | |
| 62 | + if app.tonNetwork.usdtAvailable { | |
| 63 | + HStack(alignment: .firstTextBaseline) { | |
| 64 | + Text("USDT").font(.headline) | |
| 65 | + Spacer() | |
| 66 | + VStack(alignment: .trailing, spacing: 2) { | |
| 67 | + Text(TokenAmount.format(BigUInt(app.tonBalancesState?.usdtUnits ?? 0), decimals: 6)) | |
| 68 | + .font(.system(size: 26, weight: .bold, design: .rounded)) | |
| 69 | + .monospacedDigit() | |
| 70 | + if let fiat = fiatLine(units: app.tonBalancesState?.usdtUnits ?? 0, decimals: 6, symbol: "USDT") { | |
| 71 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 72 | + } | |
| 73 | + } | |
| 74 | + } | |
| 75 | + Divider() | |
| 76 | + } | |
| 77 | + HStack { | |
| 78 | + Text("TON (fees)").font(.subheadline).foregroundStyle(.secondary) | |
| 79 | + Spacer() | |
| 80 | + VStack(alignment: .trailing, spacing: 2) { | |
| 81 | + Text(TONService.formatTON(app.tonBalancesState?.nanotons ?? 0) + " TON") | |
| 82 | + .font(.subheadline.monospaced()) | |
| 83 | + .foregroundStyle(.secondary) | |
| 84 | + if let fiat = fiatLine(units: app.tonBalancesState?.nanotons ?? 0, decimals: 9, symbol: "TON") { | |
| 85 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 86 | + } | |
| 87 | + } | |
| 88 | + } | |
| 89 | + if app.tonBalancesState?.deployed == false, (app.tonBalancesState?.nanotons ?? 0) > 0 { | |
| 90 | + Text("Wallet contract deploys automatically with your first send.") | |
| 91 | + .font(.caption).foregroundStyle(.secondary) | |
| 92 | + } | |
| 93 | + if let error = app.tonError { | |
| 94 | + Label(error, systemImage: "wifi.exclamationmark") | |
| 95 | + .font(.caption).foregroundStyle(.orange) | |
| 96 | + } | |
| 97 | + } | |
| 98 | + .padding(14) | |
| 99 | + .background(.quaternary.opacity(0.4)) | |
| 100 | + .clipShape(RoundedRectangle(cornerRadius: 10)) | |
| 101 | + | |
| 102 | + HStack(spacing: 12) { | |
| 103 | + Button { | |
| 104 | + mode = .send | |
| 105 | + } label: { | |
| 106 | + Label("Send", systemImage: "arrow.up.circle.fill").frame(maxWidth: .infinity) | |
| 107 | + } | |
| 108 | + .buttonStyle(.borderedProminent) | |
| 109 | + Button { | |
| 110 | + mode = .receive | |
| 111 | + } label: { | |
| 112 | + Label("Receive", systemImage: "arrow.down.circle").frame(maxWidth: .infinity) | |
| 113 | + } | |
| 114 | + Button { | |
| 115 | + Task { await app.refreshTON() } | |
| 116 | + } label: { | |
| 117 | + Image(systemName: "arrow.clockwise") | |
| 118 | + } | |
| 119 | + .help("Refresh") | |
| 120 | + } | |
| 121 | + | |
| 122 | + Text("ed25519 (wallet v4R2) from your existing recovery phrase — note: Tonkeeper's default import expects TON-native 24-word phrases, not BIP-39. USDT is a jetton: sends attach ~0.07 TON for fees, the unused part is refunded.") | |
| 123 | + .font(.caption) | |
| 124 | + .foregroundStyle(.secondary) | |
| 125 | + | |
| 126 | + Picker("Network", selection: Binding( | |
| 127 | + get: { app.tonNetwork }, | |
| 128 | + set: { newValue in Task { await app.switchTONNetwork(to: newValue) } } | |
| 129 | + )) { | |
| 130 | + ForEach(TONService.TONNetwork.allCases, id: \.self) { network in | |
| 131 | + Text(network.displayName).tag(network) | |
| 132 | + } | |
| 133 | + } | |
| 134 | + .pickerStyle(.segmented) | |
| 135 | + } | |
| 136 | + } | |
| 137 | + | |
| 138 | + private func fiatLine(units: UInt64, decimals: Int, symbol: String) -> String? { | |
| 139 | + guard app.pricesEnabled, units > 0, let price = app.fiatPrices[symbol] else { return nil } | |
| 140 | + let value = PriceService.fiatValue(units: BigUInt(units), decimals: decimals, price: price) | |
| 141 | + return "≈ " + PriceService.formatFiat(value, currency: app.fiatCurrency) | |
| 142 | + } | |
| 143 | + | |
| 144 | + // MARK: - Receive | |
| 145 | + | |
| 146 | + private var receive: some View { | |
| 147 | + VStack(spacing: 14) { | |
| 148 | + if let address = app.tonAddress { | |
| 149 | + if let qr = QRCode.image(for: address) { | |
| 150 | + Image(nsImage: qr) | |
| 151 | + .interpolation(.none) | |
| 152 | + .resizable() | |
| 153 | + .frame(width: 200, height: 200) | |
| 154 | + .background(.white) | |
| 155 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 156 | + } | |
| 157 | + Text(address) | |
| 158 | + .font(.callout.monospaced()) | |
| 159 | + .textSelection(.enabled) | |
| 160 | + .padding(8) | |
| 161 | + .background(.quaternary.opacity(0.4)) | |
| 162 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 163 | + CopyButton(text: address) | |
| 164 | + Text("One address for TON and every jetton on \(app.tonNetwork.displayName).") | |
| 165 | + .font(.caption).foregroundStyle(.secondary) | |
| 166 | + } | |
| 167 | + Button("Back") { mode = .overview } | |
| 168 | + } | |
| 169 | + .frame(maxWidth: .infinity) | |
| 170 | + } | |
| 171 | + | |
| 172 | + // MARK: - Send | |
| 173 | + | |
| 174 | + private var send: some View { | |
| 175 | + VStack(alignment: .leading, spacing: 12) { | |
| 176 | + if let ref = sentRef { | |
| 177 | + sentView(ref) | |
| 178 | + } else if let prepared { | |
| 179 | + confirmView(prepared) | |
| 180 | + } else { | |
| 181 | + sendForm | |
| 182 | + } | |
| 183 | + } | |
| 184 | + } | |
| 185 | + | |
| 186 | + private var sendForm: some View { | |
| 187 | + VStack(alignment: .leading, spacing: 12) { | |
| 188 | + if app.tonNetwork.usdtAvailable { | |
| 189 | + Picker("Asset", selection: $sendUSDT) { | |
| 190 | + Text("TON").tag(false) | |
| 191 | + Text("USDT").tag(true) | |
| 192 | + } | |
| 193 | + .pickerStyle(.segmented) | |
| 194 | + } | |
| 195 | + TextField("Recipient (UQ… / EQ…)", text: $recipient) | |
| 196 | + .textFieldStyle(.roundedBorder) | |
| 197 | + .font(.body.monospaced()) | |
| 198 | + .autocorrectionDisabled() | |
| 199 | + if !recipient.isEmpty && !TONService.validate(address: recipient) { | |
| 200 | + Label("Not a valid TON address", systemImage: "xmark.circle") | |
| 201 | + .font(.caption).foregroundStyle(.red) | |
| 202 | + } | |
| 203 | + HStack { | |
| 204 | + TextField("Amount", text: $amountInput) | |
| 205 | + .textFieldStyle(.roundedBorder) | |
| 206 | + .font(.body.monospaced()) | |
| 207 | + Text(sendUSDT ? "USDT" : "TON").foregroundStyle(.secondary) | |
| 208 | + } | |
| 209 | + Text(sendUSDT | |
| 210 | + ? "Balance: \(TokenAmount.format(BigUInt(app.tonBalancesState?.usdtUnits ?? 0), decimals: 6)) USDT" | |
| 211 | + : "Balance: \(TONService.formatTON(app.tonBalancesState?.nanotons ?? 0)) TON") | |
| 212 | + .font(.caption).foregroundStyle(.secondary) | |
| 213 | + if let errorMessage { | |
| 214 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 215 | + } | |
| 216 | + HStack { | |
| 217 | + Button("Back") { mode = .overview; errorMessage = nil } | |
| 218 | + Spacer() | |
| 219 | + if busy { ProgressView().controlSize(.small) } | |
| 220 | + Button("Review") { estimate() } | |
| 221 | + .buttonStyle(.borderedProminent) | |
| 222 | + .disabled(!formValid || busy) | |
| 223 | + } | |
| 224 | + } | |
| 225 | + } | |
| 226 | + | |
| 227 | + private var parsedAmount: UInt64? { | |
| 228 | + sendUSDT ? TONService.parseUSDT(amountInput) : TONService.parseTON(amountInput) | |
| 229 | + } | |
| 230 | + | |
| 231 | + private var formValid: Bool { | |
| 232 | + TONService.validate(address: recipient) && (parsedAmount ?? 0) > 0 | |
| 233 | + } | |
| 234 | + | |
| 235 | + private func estimate() { | |
| 236 | + guard let amount = parsedAmount else { return } | |
| 237 | + errorMessage = nil | |
| 238 | + busy = true | |
| 239 | + let to = recipient.trimmingCharacters(in: .whitespacesAndNewlines) | |
| 240 | + let usdt = sendUSDT | |
| 241 | + Task { | |
| 242 | + do { | |
| 243 | + prepared = try await app.tonService.estimateSend( | |
| 244 | + to: to, amountUnits: amount, isUSDT: usdt) | |
| 245 | + } catch { | |
| 246 | + errorMessage = error.localizedDescription | |
| 247 | + } | |
| 248 | + busy = false | |
| 249 | + } | |
| 250 | + } | |
| 251 | + | |
| 252 | + private func confirmView(_ p: TONService.PreparedTONSend) -> some View { | |
| 253 | + VStack(alignment: .leading, spacing: 12) { | |
| 254 | + Text("Confirm transaction").font(.headline) | |
| 255 | + Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 8) { | |
| 256 | + GridRow { | |
| 257 | + Text("Recipient").foregroundStyle(.secondary) | |
| 258 | + Text(p.recipient).font(.callout.monospaced()) | |
| 259 | + .textSelection(.enabled) | |
| 260 | + .lineLimit(1).truncationMode(.middle) | |
| 261 | + } | |
| 262 | + GridRow { | |
| 263 | + Text("Amount").foregroundStyle(.secondary) | |
| 264 | + Text(p.isUSDT | |
| 265 | + ? "\(TokenAmount.format(BigUInt(p.amountUnits), decimals: 6)) USDT" | |
| 266 | + : "\(TONService.formatTON(p.amountUnits)) TON") | |
| 267 | + .fontWeight(.semibold) | |
| 268 | + } | |
| 269 | + GridRow { | |
| 270 | + Text("Network").foregroundStyle(.secondary) | |
| 271 | + Text(p.network.displayName) | |
| 272 | + } | |
| 273 | + GridRow { | |
| 274 | + Text("Est. fee").foregroundStyle(.secondary) | |
| 275 | + Text("≈ \(TONService.formatTON(p.estimatedFeeNanotons)) TON" + (p.isUSDT ? " (excess refunded)" : "")) | |
| 276 | + } | |
| 277 | + } | |
| 278 | + .font(.callout) | |
| 279 | + Divider() | |
| 280 | + SecureField("Vault password to sign", text: $password) | |
| 281 | + .textFieldStyle(.roundedBorder) | |
| 282 | + if let errorMessage { | |
| 283 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 284 | + } | |
| 285 | + HStack { | |
| 286 | + Button("Back") { | |
| 287 | + prepared = nil | |
| 288 | + password = "" | |
| 289 | + } | |
| 290 | + Spacer() | |
| 291 | + if busy { ProgressView().controlSize(.small) } | |
| 292 | + Button("Sign & send") { broadcast(p) } | |
| 293 | + .buttonStyle(.borderedProminent) | |
| 294 | + .disabled(password.isEmpty || busy) | |
| 295 | + } | |
| 296 | + } | |
| 297 | + } | |
| 298 | + | |
| 299 | + private func broadcast(_ p: TONService.PreparedTONSend) { | |
| 300 | + busy = true | |
| 301 | + errorMessage = nil | |
| 302 | + let candidate = password | |
| 303 | + let manager = app.keyManager | |
| 304 | + Task { | |
| 305 | + do { | |
| 306 | + let mnemonic = try await Task.detached { | |
| 307 | + try manager.unlock(password: candidate).mnemonic | |
| 308 | + }.value | |
| 309 | + let ref = try await app.tonService.send(p, mnemonic: mnemonic) | |
| 310 | + password = "" | |
| 311 | + sentRef = ref | |
| 312 | + await app.refreshTON() | |
| 313 | + } catch { | |
| 314 | + errorMessage = error.localizedDescription | |
| 315 | + } | |
| 316 | + busy = false | |
| 317 | + } | |
| 318 | + } | |
| 319 | + | |
| 320 | + private func sentView(_ ref: String) -> some View { | |
| 321 | + VStack(spacing: 12) { | |
| 322 | + Image(systemName: "paperplane.circle.fill") | |
| 323 | + .font(.system(size: 38)).foregroundStyle(.green) | |
| 324 | + Text("Transaction sent").font(.headline) | |
| 325 | + Text("It will appear on the explorer within seconds.") | |
| 326 | + .font(.callout).foregroundStyle(.secondary) | |
| 327 | + if let address = app.tonAddress { | |
| 328 | + Link("View account on Tonviewer", destination: app.tonNetwork.explorerAddressURL(address)) | |
| 329 | + } | |
| 330 | + Button("Done") { | |
| 331 | + sentRef = nil | |
| 332 | + prepared = nil | |
| 333 | + recipient = "" | |
| 334 | + amountInput = "" | |
| 335 | + mode = .overview | |
| 336 | + } | |
| 337 | + .buttonStyle(.borderedProminent) | |
| 338 | + } | |
| 339 | + .frame(maxWidth: .infinity) | |
| 340 | + } | |
| 341 | +} | |
| 342 | + | |
| 343 | +extension TONService.TONNetwork { | |
| 344 | + var usdtAvailable: Bool { usdtMaster != nil } | |
| 345 | +} | |
added
Sources/OSVaultKit/Views/Tron/TronView.swift
+340 −0
@@ -0,0 +1,340 @@ | ||
| 1 | +// | |
| 2 | +// TronView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// Tron panel: USDT (TRC-20) + TRX balances, receive, send with the energy | |
| 13 | +/// burn estimate surfaced before signing, Nile/mainnet switch. | |
| 14 | +struct TronView: View { | |
| 15 | + @EnvironmentObject var app: AppState | |
| 16 | + @Environment(\.dismiss) private var dismiss | |
| 17 | + | |
| 18 | + enum Mode { case overview, receive, send } | |
| 19 | + @State private var mode: Mode = .overview | |
| 20 | + | |
| 21 | + @State private var sendUSDT = true | |
| 22 | + @State private var recipient = "" | |
| 23 | + @State private var amountInput = "" | |
| 24 | + @State private var prepared: TronService.PreparedTronSend? | |
| 25 | + @State private var password = "" | |
| 26 | + @State private var sending = false | |
| 27 | + @State private var estimating = false | |
| 28 | + @State private var sentTxid: String? | |
| 29 | + @State private var errorMessage: String? | |
| 30 | + | |
| 31 | + var body: some View { | |
| 32 | + VStack(alignment: .leading, spacing: 16) { | |
| 33 | + header | |
| 34 | + switch mode { | |
| 35 | + case .overview: overview | |
| 36 | + case .receive: receive | |
| 37 | + case .send: send | |
| 38 | + } | |
| 39 | + } | |
| 40 | + .padding(24) | |
| 41 | + .frame(width: 470) | |
| 42 | + } | |
| 43 | + | |
| 44 | + private var header: some View { | |
| 45 | + HStack { | |
| 46 | + Text("Tron").font(.title2.bold()) | |
| 47 | + Spacer() | |
| 48 | + Text(app.tronNetwork.isTestnet ? "NILE · test" : "MAINNET") | |
| 49 | + .font(.caption.weight(.bold)) | |
| 50 | + .padding(.horizontal, 10).padding(.vertical, 4) | |
| 51 | + .background(app.tronNetwork.isTestnet ? Color.orange.opacity(0.25) : Color.red.opacity(0.22)) | |
| 52 | + .foregroundStyle(app.tronNetwork.isTestnet ? Color.orange : Color.red) | |
| 53 | + .clipShape(Capsule()) | |
| 54 | + Button("Done") { dismiss() } | |
| 55 | + } | |
| 56 | + } | |
| 57 | + | |
| 58 | + // MARK: - Overview | |
| 59 | + | |
| 60 | + private var overview: some View { | |
| 61 | + VStack(alignment: .leading, spacing: 14) { | |
| 62 | + VStack(alignment: .leading, spacing: 10) { | |
| 63 | + HStack(alignment: .firstTextBaseline) { | |
| 64 | + Text("USDT").font(.headline) | |
| 65 | + Spacer() | |
| 66 | + VStack(alignment: .trailing, spacing: 2) { | |
| 67 | + Text(TokenAmount.format(BigUInt(app.tronBalances?.usdtUnits ?? 0), decimals: 6)) | |
| 68 | + .font(.system(size: 26, weight: .bold, design: .rounded)) | |
| 69 | + .monospacedDigit() | |
| 70 | + if let fiat = fiatLine(units: app.tronBalances?.usdtUnits ?? 0, decimals: 6, symbol: "USDT") { | |
| 71 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 72 | + } | |
| 73 | + } | |
| 74 | + } | |
| 75 | + Divider() | |
| 76 | + HStack { | |
| 77 | + Text("TRX (fees)").font(.subheadline).foregroundStyle(.secondary) | |
| 78 | + Spacer() | |
| 79 | + VStack(alignment: .trailing, spacing: 2) { | |
| 80 | + Text(TronService.formatTRX(app.tronBalances?.trxSun ?? 0) + " TRX") | |
| 81 | + .font(.subheadline.monospaced()) | |
| 82 | + .foregroundStyle(.secondary) | |
| 83 | + if let fiat = fiatLine(units: app.tronBalances?.trxSun ?? 0, decimals: 6, symbol: "TRX") { | |
| 84 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 85 | + } | |
| 86 | + } | |
| 87 | + } | |
| 88 | + if let error = app.tronError { | |
| 89 | + Label(error, systemImage: "wifi.exclamationmark") | |
| 90 | + .font(.caption).foregroundStyle(.orange) | |
| 91 | + } | |
| 92 | + } | |
| 93 | + .padding(14) | |
| 94 | + .background(.quaternary.opacity(0.4)) | |
| 95 | + .clipShape(RoundedRectangle(cornerRadius: 10)) | |
| 96 | + | |
| 97 | + HStack(spacing: 12) { | |
| 98 | + Button { | |
| 99 | + mode = .send | |
| 100 | + } label: { | |
| 101 | + Label("Send", systemImage: "arrow.up.circle.fill").frame(maxWidth: .infinity) | |
| 102 | + } | |
| 103 | + .buttonStyle(.borderedProminent) | |
| 104 | + Button { | |
| 105 | + mode = .receive | |
| 106 | + } label: { | |
| 107 | + Label("Receive", systemImage: "arrow.down.circle").frame(maxWidth: .infinity) | |
| 108 | + } | |
| 109 | + Button { | |
| 110 | + Task { await app.refreshTron() } | |
| 111 | + } label: { | |
| 112 | + Image(systemName: "arrow.clockwise") | |
| 113 | + } | |
| 114 | + .help("Refresh") | |
| 115 | + } | |
| 116 | + | |
| 117 | + Text("secp256k1 at m/44'/195'/0'/0/0 from your existing recovery phrase. USDT transfers burn TRX for energy (~13–27 TRX without staked energy) — the exact estimate is shown before you sign.") | |
| 118 | + .font(.caption) | |
| 119 | + .foregroundStyle(.secondary) | |
| 120 | + | |
| 121 | + Picker("Network", selection: Binding( | |
| 122 | + get: { app.tronNetwork }, | |
| 123 | + set: { newValue in Task { await app.switchTronNetwork(to: newValue) } } | |
| 124 | + )) { | |
| 125 | + ForEach(TronService.TronNetwork.allCases, id: \.self) { network in | |
| 126 | + Text(network.displayName).tag(network) | |
| 127 | + } | |
| 128 | + } | |
| 129 | + .pickerStyle(.segmented) | |
| 130 | + } | |
| 131 | + } | |
| 132 | + | |
| 133 | + private func fiatLine(units: UInt64, decimals: Int, symbol: String) -> String? { | |
| 134 | + guard app.pricesEnabled, units > 0, let price = app.fiatPrices[symbol] else { return nil } | |
| 135 | + let value = PriceService.fiatValue(units: BigUInt(units), decimals: decimals, price: price) | |
| 136 | + return "≈ " + PriceService.formatFiat(value, currency: app.fiatCurrency) | |
| 137 | + } | |
| 138 | + | |
| 139 | + // MARK: - Receive | |
| 140 | + | |
| 141 | + private var receive: some View { | |
| 142 | + VStack(spacing: 14) { | |
| 143 | + if let address = app.tronAddress { | |
| 144 | + if let qr = QRCode.image(for: address) { | |
| 145 | + Image(nsImage: qr) | |
| 146 | + .interpolation(.none) | |
| 147 | + .resizable() | |
| 148 | + .frame(width: 200, height: 200) | |
| 149 | + .background(.white) | |
| 150 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 151 | + } | |
| 152 | + Text(address) | |
| 153 | + .font(.callout.monospaced()) | |
| 154 | + .textSelection(.enabled) | |
| 155 | + .padding(8) | |
| 156 | + .background(.quaternary.opacity(0.4)) | |
| 157 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 158 | + CopyButton(text: address) | |
| 159 | + Text("One address for TRX and every TRC-20 token on \(app.tronNetwork.displayName).") | |
| 160 | + .font(.caption).foregroundStyle(.secondary) | |
| 161 | + } | |
| 162 | + Button("Back") { mode = .overview } | |
| 163 | + } | |
| 164 | + .frame(maxWidth: .infinity) | |
| 165 | + } | |
| 166 | + | |
| 167 | + // MARK: - Send | |
| 168 | + | |
| 169 | + private var send: some View { | |
| 170 | + VStack(alignment: .leading, spacing: 12) { | |
| 171 | + if let txid = sentTxid { | |
| 172 | + sentView(txid) | |
| 173 | + } else if let prepared { | |
| 174 | + confirmView(prepared) | |
| 175 | + } else { | |
| 176 | + sendForm | |
| 177 | + } | |
| 178 | + } | |
| 179 | + } | |
| 180 | + | |
| 181 | + private var sendForm: some View { | |
| 182 | + VStack(alignment: .leading, spacing: 12) { | |
| 183 | + Picker("Asset", selection: $sendUSDT) { | |
| 184 | + Text("USDT").tag(true) | |
| 185 | + Text("TRX").tag(false) | |
| 186 | + } | |
| 187 | + .pickerStyle(.segmented) | |
| 188 | + TextField("Recipient (T…)", text: $recipient) | |
| 189 | + .textFieldStyle(.roundedBorder) | |
| 190 | + .font(.body.monospaced()) | |
| 191 | + .autocorrectionDisabled() | |
| 192 | + if !recipient.isEmpty && !TronService.validate(address: recipient) { | |
| 193 | + Label("Not a valid Tron address", systemImage: "xmark.circle") | |
| 194 | + .font(.caption).foregroundStyle(.red) | |
| 195 | + } | |
| 196 | + HStack { | |
| 197 | + TextField("Amount", text: $amountInput) | |
| 198 | + .textFieldStyle(.roundedBorder) | |
| 199 | + .font(.body.monospaced()) | |
| 200 | + Text(sendUSDT ? "USDT" : "TRX").foregroundStyle(.secondary) | |
| 201 | + } | |
| 202 | + Text(sendUSDT | |
| 203 | + ? "Balance: \(TokenAmount.format(BigUInt(app.tronBalances?.usdtUnits ?? 0), decimals: 6)) USDT" | |
| 204 | + : "Balance: \(TronService.formatTRX(app.tronBalances?.trxSun ?? 0)) TRX") | |
| 205 | + .font(.caption).foregroundStyle(.secondary) | |
| 206 | + if let errorMessage { | |
| 207 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 208 | + } | |
| 209 | + HStack { | |
| 210 | + Button("Back") { mode = .overview; errorMessage = nil } | |
| 211 | + Spacer() | |
| 212 | + if estimating { ProgressView().controlSize(.small) } | |
| 213 | + Button("Review") { estimate() } | |
| 214 | + .buttonStyle(.borderedProminent) | |
| 215 | + .disabled(!formValid || estimating) | |
| 216 | + } | |
| 217 | + } | |
| 218 | + } | |
| 219 | + | |
| 220 | + private var parsedAmount: UInt64? { | |
| 221 | + sendUSDT ? TronService.parseUSDT(amountInput) : TronService.parseTRX(amountInput) | |
| 222 | + } | |
| 223 | + | |
| 224 | + private var formValid: Bool { | |
| 225 | + TronService.validate(address: recipient) && (parsedAmount ?? 0) > 0 | |
| 226 | + } | |
| 227 | + | |
| 228 | + private func estimate() { | |
| 229 | + guard let amount = parsedAmount else { return } | |
| 230 | + errorMessage = nil | |
| 231 | + estimating = true | |
| 232 | + let to = recipient.trimmingCharacters(in: .whitespacesAndNewlines) | |
| 233 | + let usdt = sendUSDT | |
| 234 | + Task { | |
| 235 | + do { | |
| 236 | + prepared = try await app.tronService.estimateSend( | |
| 237 | + to: to, amountUnits: amount, isUSDT: usdt) | |
| 238 | + } catch { | |
| 239 | + errorMessage = error.localizedDescription | |
| 240 | + } | |
| 241 | + estimating = false | |
| 242 | + } | |
| 243 | + } | |
| 244 | + | |
| 245 | + private func confirmView(_ p: TronService.PreparedTronSend) -> some View { | |
| 246 | + VStack(alignment: .leading, spacing: 12) { | |
| 247 | + Text("Confirm transaction").font(.headline) | |
| 248 | + Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 8) { | |
| 249 | + GridRow { | |
| 250 | + Text("Recipient").foregroundStyle(.secondary) | |
| 251 | + Text(p.recipient).font(.callout.monospaced()) | |
| 252 | + .textSelection(.enabled) | |
| 253 | + .lineLimit(1).truncationMode(.middle) | |
| 254 | + } | |
| 255 | + GridRow { | |
| 256 | + Text("Amount").foregroundStyle(.secondary) | |
| 257 | + Text(p.isUSDT | |
| 258 | + ? "\(TokenAmount.format(BigUInt(p.amountUnits), decimals: 6)) USDT" | |
| 259 | + : "\(TronService.formatTRX(p.amountUnits)) TRX") | |
| 260 | + .fontWeight(.semibold) | |
| 261 | + } | |
| 262 | + GridRow { | |
| 263 | + Text("Network").foregroundStyle(.secondary) | |
| 264 | + Text(p.network.displayName) | |
| 265 | + } | |
| 266 | + GridRow { | |
| 267 | + Text("Est. fee").foregroundStyle(.secondary) | |
| 268 | + Text("≤ \(TronService.formatTRX(p.estimatedFeeSun)) TRX (burned)") | |
| 269 | + } | |
| 270 | + } | |
| 271 | + .font(.callout) | |
| 272 | + if p.isUSDT, (app.tronBalances?.trxSun ?? 0) < p.estimatedFeeSun { | |
| 273 | + Label("Not enough TRX to cover the energy burn. Top up TRX first.", | |
| 274 | + systemImage: "exclamationmark.triangle") | |
| 275 | + .font(.caption) | |
| 276 | + .foregroundStyle(.red) | |
| 277 | + } | |
| 278 | + Divider() | |
| 279 | + SecureField("Vault password to sign", text: $password) | |
| 280 | + .textFieldStyle(.roundedBorder) | |
| 281 | + if let errorMessage { | |
| 282 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 283 | + } | |
| 284 | + HStack { | |
| 285 | + Button("Back") { | |
| 286 | + prepared = nil | |
| 287 | + password = "" | |
| 288 | + } | |
| 289 | + Spacer() | |
| 290 | + if sending { ProgressView().controlSize(.small) } | |
| 291 | + Button("Sign & send") { broadcast(p) } | |
| 292 | + .buttonStyle(.borderedProminent) | |
| 293 | + .disabled(password.isEmpty || sending) | |
| 294 | + } | |
| 295 | + } | |
| 296 | + } | |
| 297 | + | |
| 298 | + private func broadcast(_ p: TronService.PreparedTronSend) { | |
| 299 | + sending = true | |
| 300 | + errorMessage = nil | |
| 301 | + let candidate = password | |
| 302 | + let manager = app.keyManager | |
| 303 | + Task { | |
| 304 | + do { | |
| 305 | + let mnemonic = try await Task.detached { | |
| 306 | + try manager.unlock(password: candidate).mnemonic | |
| 307 | + }.value | |
| 308 | + let txid = try await app.tronService.send(p, mnemonic: mnemonic) | |
| 309 | + password = "" | |
| 310 | + sentTxid = txid | |
| 311 | + await app.refreshTron() | |
| 312 | + } catch { | |
| 313 | + errorMessage = error.localizedDescription | |
| 314 | + } | |
| 315 | + sending = false | |
| 316 | + } | |
| 317 | + } | |
| 318 | + | |
| 319 | + private func sentView(_ txid: String) -> some View { | |
| 320 | + VStack(spacing: 12) { | |
| 321 | + Image(systemName: "paperplane.circle.fill") | |
| 322 | + .font(.system(size: 38)).foregroundStyle(.green) | |
| 323 | + Text("Transaction sent").font(.headline) | |
| 324 | + Text(txid) | |
| 325 | + .font(.caption.monospaced()) | |
| 326 | + .textSelection(.enabled) | |
| 327 | + .lineLimit(1).truncationMode(.middle) | |
| 328 | + Link("View on Tronscan", destination: app.tronNetwork.explorerTxURL(txid)) | |
| 329 | + Button("Done") { | |
| 330 | + sentTxid = nil | |
| 331 | + prepared = nil | |
| 332 | + recipient = "" | |
| 333 | + amountInput = "" | |
| 334 | + mode = .overview | |
| 335 | + } | |
| 336 | + .buttonStyle(.borderedProminent) | |
| 337 | + } | |
| 338 | + .frame(maxWidth: .infinity) | |
| 339 | + } | |
| 340 | +} | |
added
Sources/OSVaultKit/Views/XRPL/XRPLView.swift
+389 −0
@@ -0,0 +1,389 @@ | ||
| 1 | +// | |
| 2 | +// XRPLView.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import SwiftUI | |
| 10 | +import BigInt | |
| 11 | + | |
| 12 | +/// XRP Ledger panel: XRP + RLUSD balances (reserve shown as locked), receive, | |
| 13 | +/// send with trustline checks, one-tap RLUSD trustline, testnet/mainnet switch. | |
| 14 | +struct XRPLView: View { | |
| 15 | + @EnvironmentObject var app: AppState | |
| 16 | + @Environment(\.dismiss) private var dismiss | |
| 17 | + | |
| 18 | + enum Mode { case overview, receive, send } | |
| 19 | + @State private var mode: Mode = .overview | |
| 20 | + | |
| 21 | + @State private var sendRLUSD = false | |
| 22 | + @State private var recipient = "" | |
| 23 | + @State private var amountInput = "" | |
| 24 | + @State private var prepared: XRPLService.PreparedXRPLSend? | |
| 25 | + @State private var password = "" | |
| 26 | + @State private var trustlinePassword = "" | |
| 27 | + @State private var showTrustline = false | |
| 28 | + @State private var busy = false | |
| 29 | + @State private var sentHash: String? | |
| 30 | + @State private var errorMessage: String? | |
| 31 | + | |
| 32 | + var body: some View { | |
| 33 | + VStack(alignment: .leading, spacing: 16) { | |
| 34 | + header | |
| 35 | + switch mode { | |
| 36 | + case .overview: overview | |
| 37 | + case .receive: receive | |
| 38 | + case .send: send | |
| 39 | + } | |
| 40 | + } | |
| 41 | + .padding(24) | |
| 42 | + .frame(width: 470) | |
| 43 | + } | |
| 44 | + | |
| 45 | + private var header: some View { | |
| 46 | + HStack { | |
| 47 | + Text("XRP Ledger").font(.title2.bold()) | |
| 48 | + Spacer() | |
| 49 | + Text(app.xrplNetwork.isTestnet ? "TESTNET" : "MAINNET") | |
| 50 | + .font(.caption.weight(.bold)) | |
| 51 | + .padding(.horizontal, 10).padding(.vertical, 4) | |
| 52 | + .background(app.xrplNetwork.isTestnet ? Color.orange.opacity(0.25) : Color.blue.opacity(0.2)) | |
| 53 | + .foregroundStyle(app.xrplNetwork.isTestnet ? Color.orange : Color.blue) | |
| 54 | + .clipShape(Capsule()) | |
| 55 | + Button("Done") { dismiss() } | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | + // MARK: - Overview | |
| 60 | + | |
| 61 | + private var overview: some View { | |
| 62 | + VStack(alignment: .leading, spacing: 14) { | |
| 63 | + VStack(alignment: .leading, spacing: 10) { | |
| 64 | + HStack(alignment: .firstTextBaseline) { | |
| 65 | + Text("XRP").font(.headline) | |
| 66 | + Spacer() | |
| 67 | + VStack(alignment: .trailing, spacing: 2) { | |
| 68 | + Text(XRPLService.formatXRP(app.xrplBalances?.drops ?? 0)) | |
| 69 | + .font(.system(size: 26, weight: .bold, design: .rounded)) | |
| 70 | + .monospacedDigit() | |
| 71 | + if let fiat = fiatLine(units: app.xrplBalances?.drops ?? 0, decimals: 6, symbol: "XRP") { | |
| 72 | + Text(fiat).font(.caption).foregroundStyle(.secondary) | |
| 73 | + } | |
| 74 | + } | |
| 75 | + } | |
| 76 | + if let balances = app.xrplBalances, balances.accountExists { | |
| 77 | + Text("Spendable: \(XRPLService.formatXRP(balances.spendableDrops)) XRP (\(XRPLService.formatXRP(balances.reserveDrops)) locked as reserve)") | |
| 78 | + .font(.caption).foregroundStyle(.secondary) | |
| 79 | + } | |
| 80 | + Divider() | |
| 81 | + HStack(alignment: .firstTextBaseline) { | |
| 82 | + Text("RLUSD").font(.headline) | |
| 83 | + Spacer() | |
| 84 | + if app.xrplBalances?.hasRLUSDTrustline == true { | |
| 85 | + Text(app.xrplBalances?.rlusdValue ?? "0") | |
| 86 | + .font(.title3.weight(.semibold)).monospacedDigit() | |
| 87 | + } else { | |
| 88 | + Text("no trustline").font(.callout).foregroundStyle(.secondary) | |
| 89 | + } | |
| 90 | + } | |
| 91 | + if app.xrplBalances?.accountExists == false { | |
| 92 | + Label("Account not funded yet — the first deposit must be at least 1 XRP.", | |
| 93 | + systemImage: "info.circle") | |
| 94 | + .font(.caption).foregroundStyle(.orange) | |
| 95 | + } | |
| 96 | + if let error = app.xrplError { | |
| 97 | + Label(error, systemImage: "wifi.exclamationmark") | |
| 98 | + .font(.caption).foregroundStyle(.orange) | |
| 99 | + } | |
| 100 | + } | |
| 101 | + .padding(14) | |
| 102 | + .background(.quaternary.opacity(0.4)) | |
| 103 | + .clipShape(RoundedRectangle(cornerRadius: 10)) | |
| 104 | + | |
| 105 | + HStack(spacing: 12) { | |
| 106 | + Button { | |
| 107 | + mode = .send | |
| 108 | + } label: { | |
| 109 | + Label("Send", systemImage: "arrow.up.circle.fill").frame(maxWidth: .infinity) | |
| 110 | + } | |
| 111 | + .buttonStyle(.borderedProminent) | |
| 112 | + Button { | |
| 113 | + mode = .receive | |
| 114 | + } label: { | |
| 115 | + Label("Receive", systemImage: "arrow.down.circle").frame(maxWidth: .infinity) | |
| 116 | + } | |
| 117 | + Button { | |
| 118 | + Task { await app.refreshXRPL() } | |
| 119 | + } label: { | |
| 120 | + Image(systemName: "arrow.clockwise") | |
| 121 | + } | |
| 122 | + .help("Refresh") | |
| 123 | + } | |
| 124 | + | |
| 125 | + if app.xrplBalances?.hasRLUSDTrustline != true, app.xrplBalances?.accountExists == true { | |
| 126 | + DisclosureGroup("Enable RLUSD (create trustline)", isExpanded: $showTrustline) { | |
| 127 | + VStack(alignment: .leading, spacing: 8) { | |
| 128 | + Text("A one-time transaction that lets this account hold RLUSD. Locks 0.2 XRP of reserve.") | |
| 129 | + .font(.caption).foregroundStyle(.secondary) | |
| 130 | + HStack { | |
| 131 | + SecureField("Vault password", text: $trustlinePassword) | |
| 132 | + .textFieldStyle(.roundedBorder) | |
| 133 | + Button("Enable") { createTrustline() } | |
| 134 | + .disabled(trustlinePassword.isEmpty || busy) | |
| 135 | + } | |
| 136 | + if let errorMessage { | |
| 137 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 138 | + } | |
| 139 | + } | |
| 140 | + .padding(.top, 6) | |
| 141 | + } | |
| 142 | + .font(.callout) | |
| 143 | + } | |
| 144 | + | |
| 145 | + Text("secp256k1 at m/44'/144'/0'/0/0 from your existing recovery phrase. Fees are ~12 drops (0.000012 XRP).") | |
| 146 | + .font(.caption) | |
| 147 | + .foregroundStyle(.secondary) | |
| 148 | + | |
| 149 | + Picker("Network", selection: Binding( | |
| 150 | + get: { app.xrplNetwork }, | |
| 151 | + set: { newValue in Task { await app.switchXRPLNetwork(to: newValue) } } | |
| 152 | + )) { | |
| 153 | + ForEach(XRPLService.XRPLNetwork.allCases, id: \.self) { network in | |
| 154 | + Text(network.displayName).tag(network) | |
| 155 | + } | |
| 156 | + } | |
| 157 | + .pickerStyle(.segmented) | |
| 158 | + } | |
| 159 | + } | |
| 160 | + | |
| 161 | + private func fiatLine(units: UInt64, decimals: Int, symbol: String) -> String? { | |
| 162 | + guard app.pricesEnabled, units > 0, let price = app.fiatPrices[symbol] else { return nil } | |
| 163 | + let value = PriceService.fiatValue(units: BigUInt(units), decimals: decimals, price: price) | |
| 164 | + return "≈ " + PriceService.formatFiat(value, currency: app.fiatCurrency) | |
| 165 | + } | |
| 166 | + | |
| 167 | + private func createTrustline() { | |
| 168 | + busy = true | |
| 169 | + errorMessage = nil | |
| 170 | + let candidate = trustlinePassword | |
| 171 | + let manager = app.keyManager | |
| 172 | + Task { | |
| 173 | + do { | |
| 174 | + let mnemonic = try await Task.detached { | |
| 175 | + try manager.unlock(password: candidate).mnemonic | |
| 176 | + }.value | |
| 177 | + _ = try await app.xrplService.createRLUSDTrustline(mnemonic: mnemonic) | |
| 178 | + trustlinePassword = "" | |
| 179 | + showTrustline = false | |
| 180 | + await app.refreshXRPL() | |
| 181 | + } catch { | |
| 182 | + errorMessage = error.localizedDescription | |
| 183 | + } | |
| 184 | + busy = false | |
| 185 | + } | |
| 186 | + } | |
| 187 | + | |
| 188 | + // MARK: - Receive | |
| 189 | + | |
| 190 | + private var receive: some View { | |
| 191 | + VStack(spacing: 14) { | |
| 192 | + if let address = app.xrplAddress { | |
| 193 | + if let qr = QRCode.image(for: address) { | |
| 194 | + Image(nsImage: qr) | |
| 195 | + .interpolation(.none) | |
| 196 | + .resizable() | |
| 197 | + .frame(width: 200, height: 200) | |
| 198 | + .background(.white) | |
| 199 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 200 | + } | |
| 201 | + Text(address) | |
| 202 | + .font(.callout.monospaced()) | |
| 203 | + .textSelection(.enabled) | |
| 204 | + .padding(8) | |
| 205 | + .background(.quaternary.opacity(0.4)) | |
| 206 | + .clipShape(RoundedRectangle(cornerRadius: 8)) | |
| 207 | + CopyButton(text: address) | |
| 208 | + Text("First deposit must be ≥ 1 XRP (activates the account). RLUSD requires the trustline.") | |
| 209 | + .font(.caption).foregroundStyle(.secondary) | |
| 210 | + .multilineTextAlignment(.center) | |
| 211 | + } | |
| 212 | + Button("Back") { mode = .overview } | |
| 213 | + } | |
| 214 | + .frame(maxWidth: .infinity) | |
| 215 | + } | |
| 216 | + | |
| 217 | + // MARK: - Send | |
| 218 | + | |
| 219 | + private var send: some View { | |
| 220 | + VStack(alignment: .leading, spacing: 12) { | |
| 221 | + if let hash = sentHash { | |
| 222 | + sentView(hash) | |
| 223 | + } else if let prepared { | |
| 224 | + confirmView(prepared) | |
| 225 | + } else { | |
| 226 | + sendForm | |
| 227 | + } | |
| 228 | + } | |
| 229 | + } | |
| 230 | + | |
| 231 | + private var sendForm: some View { | |
| 232 | + VStack(alignment: .leading, spacing: 12) { | |
| 233 | + Picker("Asset", selection: $sendRLUSD) { | |
| 234 | + Text("XRP").tag(false) | |
| 235 | + Text("RLUSD").tag(true) | |
| 236 | + } | |
| 237 | + .pickerStyle(.segmented) | |
| 238 | + TextField("Recipient (r…)", text: $recipient) | |
| 239 | + .textFieldStyle(.roundedBorder) | |
| 240 | + .font(.body.monospaced()) | |
| 241 | + .autocorrectionDisabled() | |
| 242 | + if !recipient.isEmpty && !XRPLService.validate(address: recipient) { | |
| 243 | + Label("Not a valid XRPL address", systemImage: "xmark.circle") | |
| 244 | + .font(.caption).foregroundStyle(.red) | |
| 245 | + } | |
| 246 | + HStack { | |
| 247 | + TextField("Amount", text: $amountInput) | |
| 248 | + .textFieldStyle(.roundedBorder) | |
| 249 | + .font(.body.monospaced()) | |
| 250 | + Text(sendRLUSD ? "RLUSD" : "XRP").foregroundStyle(.secondary) | |
| 251 | + } | |
| 252 | + Text(sendRLUSD | |
| 253 | + ? "Balance: \(app.xrplBalances?.rlusdValue ?? "0") RLUSD" | |
| 254 | + : "Spendable: \(XRPLService.formatXRP(app.xrplBalances?.spendableDrops ?? 0)) XRP") | |
| 255 | + .font(.caption).foregroundStyle(.secondary) | |
| 256 | + if let errorMessage { | |
| 257 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 258 | + } | |
| 259 | + HStack { | |
| 260 | + Button("Back") { mode = .overview; errorMessage = nil } | |
| 261 | + Spacer() | |
| 262 | + if busy { ProgressView().controlSize(.small) } | |
| 263 | + Button("Review") { estimate() } | |
| 264 | + .buttonStyle(.borderedProminent) | |
| 265 | + .disabled(!formValid || busy) | |
| 266 | + } | |
| 267 | + } | |
| 268 | + } | |
| 269 | + | |
| 270 | + private var formValid: Bool { | |
| 271 | + guard XRPLService.validate(address: recipient) else { return false } | |
| 272 | + if sendRLUSD { | |
| 273 | + return XRPLService.validRLUSDAmount(amountInput) != nil | |
| 274 | + } | |
| 275 | + return (XRPLService.parseXRP(amountInput) ?? 0) > 0 | |
| 276 | + } | |
| 277 | + | |
| 278 | + private func estimate() { | |
| 279 | + errorMessage = nil | |
| 280 | + busy = true | |
| 281 | + let to = recipient.trimmingCharacters(in: .whitespacesAndNewlines) | |
| 282 | + let rlusd = sendRLUSD | |
| 283 | + let drops = XRPLService.parseXRP(amountInput) ?? 0 | |
| 284 | + let value = XRPLService.validRLUSDAmount(amountInput) ?? "0" | |
| 285 | + Task { | |
| 286 | + do { | |
| 287 | + prepared = try await app.xrplService.estimateSend( | |
| 288 | + to: to, amountDrops: drops, amountValue: value, isRLUSD: rlusd) | |
| 289 | + } catch { | |
| 290 | + errorMessage = error.localizedDescription | |
| 291 | + } | |
| 292 | + busy = false | |
| 293 | + } | |
| 294 | + } | |
| 295 | + | |
| 296 | + private func confirmView(_ p: XRPLService.PreparedXRPLSend) -> some View { | |
| 297 | + VStack(alignment: .leading, spacing: 12) { | |
| 298 | + Text("Confirm transaction").font(.headline) | |
| 299 | + Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 8) { | |
| 300 | + GridRow { | |
| 301 | + Text("Recipient").foregroundStyle(.secondary) | |
| 302 | + Text(p.recipient).font(.callout.monospaced()) | |
| 303 | + .textSelection(.enabled) | |
| 304 | + .lineLimit(1).truncationMode(.middle) | |
| 305 | + } | |
| 306 | + GridRow { | |
| 307 | + Text("Amount").foregroundStyle(.secondary) | |
| 308 | + Text(p.isRLUSD ? "\(p.amountValue) RLUSD" : "\(XRPLService.formatXRP(p.amountDrops)) XRP") | |
| 309 | + .fontWeight(.semibold) | |
| 310 | + } | |
| 311 | + GridRow { | |
| 312 | + Text("Network").foregroundStyle(.secondary) | |
| 313 | + Text(p.network.displayName) | |
| 314 | + } | |
| 315 | + GridRow { | |
| 316 | + Text("Fee").foregroundStyle(.secondary) | |
| 317 | + Text("\(XRPLService.formatXRP(p.feeDrops)) XRP") | |
| 318 | + } | |
| 319 | + } | |
| 320 | + .font(.callout) | |
| 321 | + if p.activatesRecipient { | |
| 322 | + Label("The recipient account doesn't exist yet — 1 XRP of the amount becomes its locked base reserve.", | |
| 323 | + systemImage: "info.circle") | |
| 324 | + .font(.caption) | |
| 325 | + .foregroundStyle(.orange) | |
| 326 | + } | |
| 327 | + Divider() | |
| 328 | + SecureField("Vault password to sign", text: $password) | |
| 329 | + .textFieldStyle(.roundedBorder) | |
| 330 | + if let errorMessage { | |
| 331 | + Text(errorMessage).foregroundStyle(.red).font(.callout) | |
| 332 | + } | |
| 333 | + HStack { | |
| 334 | + Button("Back") { | |
| 335 | + prepared = nil | |
| 336 | + password = "" | |
| 337 | + } | |
| 338 | + Spacer() | |
| 339 | + if busy { ProgressView().controlSize(.small) } | |
| 340 | + Button("Sign & send") { broadcast(p) } | |
| 341 | + .buttonStyle(.borderedProminent) | |
| 342 | + .disabled(password.isEmpty || busy) | |
| 343 | + } | |
| 344 | + } | |
| 345 | + } | |
| 346 | + | |
| 347 | + private func broadcast(_ p: XRPLService.PreparedXRPLSend) { | |
| 348 | + busy = true | |
| 349 | + errorMessage = nil | |
| 350 | + let candidate = password | |
| 351 | + let manager = app.keyManager | |
| 352 | + Task { | |
| 353 | + do { | |
| 354 | + let mnemonic = try await Task.detached { | |
| 355 | + try manager.unlock(password: candidate).mnemonic | |
| 356 | + }.value | |
| 357 | + let hash = try await app.xrplService.send(p, mnemonic: mnemonic) | |
| 358 | + password = "" | |
| 359 | + sentHash = hash | |
| 360 | + await app.refreshXRPL() | |
| 361 | + } catch { | |
| 362 | + errorMessage = error.localizedDescription | |
| 363 | + } | |
| 364 | + busy = false | |
| 365 | + } | |
| 366 | + } | |
| 367 | + | |
| 368 | + private func sentView(_ hash: String) -> some View { | |
| 369 | + VStack(spacing: 12) { | |
| 370 | + Image(systemName: "paperplane.circle.fill") | |
| 371 | + .font(.system(size: 38)).foregroundStyle(.green) | |
| 372 | + Text("Transaction sent").font(.headline) | |
| 373 | + Text(hash) | |
| 374 | + .font(.caption.monospaced()) | |
| 375 | + .textSelection(.enabled) | |
| 376 | + .lineLimit(1).truncationMode(.middle) | |
| 377 | + Link("View on XRPL Explorer", destination: app.xrplNetwork.explorerTxURL(hash)) | |
| 378 | + Button("Done") { | |
| 379 | + sentHash = nil | |
| 380 | + prepared = nil | |
| 381 | + recipient = "" | |
| 382 | + amountInput = "" | |
| 383 | + mode = .overview | |
| 384 | + } | |
| 385 | + .buttonStyle(.borderedProminent) | |
| 386 | + } | |
| 387 | + .frame(maxWidth: .infinity) | |
| 388 | + } | |
| 389 | +} | |
added
Support/Info.plist
+49 −0
@@ -0,0 +1,49 @@ | ||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + Info.plist | |
| 4 | + OS Vault | |
| 5 | + | |
| 6 | + Author: Simon-Pierre Boucher | |
| 7 | + Mail: contact@spboucher.ai | |
| 8 | +--> | |
| 9 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| 10 | +<plist version="1.0"> | |
| 11 | +<dict> | |
| 12 | + <key>CFBundleDevelopmentRegion</key> | |
| 13 | + <string>en</string> | |
| 14 | + <key>CFBundleDisplayName</key> | |
| 15 | + <string>OS Vault</string> | |
| 16 | + <key>CFBundleExecutable</key> | |
| 17 | + <string>OSVault</string> | |
| 18 | + <key>CFBundleIconFile</key> | |
| 19 | + <string>AppIcon</string> | |
| 20 | + <key>CFBundleIdentifier</key> | |
| 21 | + <string>com.zyquo.osvault</string> | |
| 22 | + <key>CFBundleInfoDictionaryVersion</key> | |
| 23 | + <string>6.0</string> | |
| 24 | + <key>CFBundleName</key> | |
| 25 | + <string>OS Vault</string> | |
| 26 | + <key>CFBundlePackageType</key> | |
| 27 | + <string>APPL</string> | |
| 28 | + <key>CFBundleShortVersionString</key> | |
| 29 | + <string>1.0.0</string> | |
| 30 | + <key>CFBundleVersion</key> | |
| 31 | + <string>6</string> | |
| 32 | + <key>LSApplicationCategoryType</key> | |
| 33 | + <string>public.app-category.finance</string> | |
| 34 | + <key>LSArchitecturePriority</key> | |
| 35 | + <array> | |
| 36 | + <string>arm64</string> | |
| 37 | + </array> | |
| 38 | + <key>LSMinimumSystemVersion</key> | |
| 39 | + <string>14.0</string> | |
| 40 | + <key>NSHighResolutionCapable</key> | |
| 41 | + <true/> | |
| 42 | + <key>NSHumanReadableCopyright</key> | |
| 43 | + <string>© 2026 Simon-Pierre Boucher</string> | |
| 44 | + <key>NSMainNibFile</key> | |
| 45 | + <string></string> | |
| 46 | + <key>NSPrincipalClass</key> | |
| 47 | + <string>NSApplication</string> | |
| 48 | +</dict> | |
| 49 | +</plist> | |
added
Support/entitlements.plist
+21 −0
@@ -0,0 +1,21 @@ | ||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + entitlements.plist | |
| 4 | + OS Vault | |
| 5 | + | |
| 6 | + Author: Simon-Pierre Boucher | |
| 7 | + Mail: contact@spboucher.ai | |
| 8 | +--> | |
| 9 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| 10 | +<plist version="1.0"> | |
| 11 | +<dict> | |
| 12 | + <!-- App Sandbox with outbound network only: the app's sole egress is | |
| 13 | + JSON-RPC to the configured Base endpoint. The encrypted vault lives | |
| 14 | + in the sandbox container's Application Support. Hardened runtime is | |
| 15 | + enabled at signing time (codesign - -options runtime). --> | |
| 16 | + <key>com.apple.security.app-sandbox</key> | |
| 17 | + <true/> | |
| 18 | + <key>com.apple.security.network.client</key> | |
| 19 | + <true/> | |
| 20 | +</dict> | |
| 21 | +</plist> | |
added
Tests/OSVaultTests/BitcoinTests.swift
+57 −0
@@ -0,0 +1,57 @@ | ||
| 1 | +// | |
| 2 | +// BitcoinTests.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import XCTest | |
| 10 | +import BitcoinDevKit | |
| 11 | +@testable import OSVaultKit | |
| 12 | + | |
| 13 | +final class BitcoinTests: XCTestCase { | |
| 14 | + | |
| 15 | + // Official BIP-84 test vector (public, not a real wallet): the | |
| 16 | + // all-"abandon" mnemonic must derive these first addresses at m/84'/0'/0'. | |
| 17 | + let vectorMnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" | |
| 18 | + | |
| 19 | + func testBIP84VectorFirstAddress() throws { | |
| 20 | + let (external, internalD) = try BitcoinService.secretDescriptors( | |
| 21 | + mnemonic: vectorMnemonic, network: .mainnet) | |
| 22 | + let wallet = try Wallet(descriptor: external, changeDescriptor: internalD, | |
| 23 | + network: .bitcoin, persister: Persister.newInMemory()) | |
| 24 | + let first = wallet.revealNextAddress(keychain: .external) | |
| 25 | + XCTAssertEqual(first.address.description, "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu") | |
| 26 | + let second = wallet.revealNextAddress(keychain: .external) | |
| 27 | + XCTAssertEqual(second.address.description, "bc1qnjg0jd8228aq7egyzacy8cys3knf9xvrerkf9g") | |
| 28 | + let change = wallet.revealNextAddress(keychain: .internal) | |
| 29 | + XCTAssertEqual(change.address.description, "bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el") | |
| 30 | + } | |
| 31 | + | |
| 32 | + func testPublicDescriptorsAreWatchOnly() throws { | |
| 33 | + let (external, _) = try BitcoinService.publicDescriptors( | |
| 34 | + mnemonic: vectorMnemonic, network: .mainnet) | |
| 35 | + // A public descriptor must not contain private key material. | |
| 36 | + XCTAssertFalse(external.description.contains("xprv")) | |
| 37 | + XCTAssertTrue(external.description.contains("xpub")) | |
| 38 | + } | |
| 39 | + | |
| 40 | + func testAddressValidationPerNetwork() { | |
| 41 | + XCTAssertTrue(BitcoinService.validate( | |
| 42 | + address: "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", network: .mainnet)) | |
| 43 | + XCTAssertFalse(BitcoinService.validate( | |
| 44 | + address: "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", network: .signet)) | |
| 45 | + XCTAssertFalse(BitcoinService.validate(address: "not-an-address", network: .mainnet)) | |
| 46 | + XCTAssertFalse(BitcoinService.validate( | |
| 47 | + address: "0x9858EfFD232B4033E47d90003D41EC34EcaEda94", network: .mainnet)) | |
| 48 | + } | |
| 49 | + | |
| 50 | + func testBTCAmountParsing() { | |
| 51 | + XCTAssertEqual(BitcoinService.parseBTC("1"), 100_000_000) | |
| 52 | + XCTAssertEqual(BitcoinService.parseBTC("0.00000001"), 1) | |
| 53 | + XCTAssertNil(BitcoinService.parseBTC("0.000000001")) // sub-sat | |
| 54 | + XCTAssertEqual(BitcoinService.formatBTC(150_000_000), "1.5") | |
| 55 | + XCTAssertEqual(BitcoinService.formatBTC(1), "0.00000001") | |
| 56 | + } | |
| 57 | +} | |
added
Tests/OSVaultTests/CoreTests.swift
+211 −0
@@ -0,0 +1,211 @@ | ||
| 1 | +// | |
| 2 | +// CoreTests.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import XCTest | |
| 10 | +import BigInt | |
| 11 | +@testable import OSVaultKit | |
| 12 | + | |
| 13 | +final class DerivationTests: XCTestCase { | |
| 14 | + | |
| 15 | + // Standard BIP-39/BIP-44 test vector (public, not a real wallet): | |
| 16 | + // the all-"abandon" mnemonic derives this well-known address at | |
| 17 | + // m/44'/60'/0'/0/0 across every major wallet implementation. | |
| 18 | + let vectorMnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" | |
| 19 | + let vectorAddress = "0x9858EfFD232B4033E47d90003D41EC34EcaEda94" | |
| 20 | + | |
| 21 | + func testKnownVectorDerivesKnownAddress() throws { | |
| 22 | + let wallet = try KeyManager.derive(mnemonic: vectorMnemonic) | |
| 23 | + XCTAssertEqual(wallet.address, vectorAddress) | |
| 24 | + XCTAssertEqual(wallet.privateKey.count, 32) | |
| 25 | + } | |
| 26 | + | |
| 27 | + func testGeneratedMnemonicIsValidAndDerives() throws { | |
| 28 | + let manager = KeyManager(vaultURL: tempVaultURL()) | |
| 29 | + let mnemonic = try manager.generateMnemonic() | |
| 30 | + XCTAssertEqual(mnemonic.split(separator: " ").count, 12) | |
| 31 | + XCTAssertTrue(KeyManager.validate(mnemonic: mnemonic)) | |
| 32 | + let wallet = try KeyManager.derive(mnemonic: mnemonic) | |
| 33 | + XCTAssertTrue(wallet.address.hasPrefix("0x")) | |
| 34 | + XCTAssertEqual(wallet.address.count, 42) | |
| 35 | + } | |
| 36 | + | |
| 37 | + func testInvalidMnemonicRejected() { | |
| 38 | + XCTAssertFalse(KeyManager.validate(mnemonic: "not a real phrase at all")) | |
| 39 | + XCTAssertFalse(KeyManager.validate(mnemonic: "abandon abandon abandon")) | |
| 40 | + // Right words, wrong checksum word. | |
| 41 | + XCTAssertFalse(KeyManager.validate(mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon")) | |
| 42 | + } | |
| 43 | + | |
| 44 | + func testNormalizationHandlesCaseAndWhitespace() throws { | |
| 45 | + let messy = " Abandon ABANDON abandon\nabandon abandon abandon abandon abandon abandon abandon abandon about " | |
| 46 | + let wallet = try KeyManager.derive(mnemonic: messy) | |
| 47 | + XCTAssertEqual(wallet.address, vectorAddress) | |
| 48 | + } | |
| 49 | +} | |
| 50 | + | |
| 51 | +final class VaultCryptoTests: XCTestCase { | |
| 52 | + | |
| 53 | + func testSealOpenRoundtrip() throws { | |
| 54 | + let secret = Data("twelve words of nothing sensitive here".utf8) | |
| 55 | + // Low iteration count keeps the test fast; production uses 600k. | |
| 56 | + let vault = try VaultCrypto.seal(secret: secret, password: "correct horse", iterations: 10_000) | |
| 57 | + let opened = try VaultCrypto.open(vault, password: "correct horse") | |
| 58 | + XCTAssertEqual(opened, secret) | |
| 59 | + } | |
| 60 | + | |
| 61 | + func testWrongPasswordFails() throws { | |
| 62 | + let vault = try VaultCrypto.seal(secret: Data("s".utf8), password: "right", iterations: 10_000) | |
| 63 | + XCTAssertThrowsError(try VaultCrypto.open(vault, password: "wrong")) { error in | |
| 64 | + XCTAssertEqual(error as? WalletError, .wrongPassword) | |
| 65 | + } | |
| 66 | + } | |
| 67 | + | |
| 68 | + func testTamperedCiphertextFails() throws { | |
| 69 | + let vault = try VaultCrypto.seal(secret: Data("s".utf8), password: "pw", iterations: 10_000) | |
| 70 | + var combined = Data(base64Encoded: vault.ciphertext)! | |
| 71 | + combined[combined.count - 1] ^= 0xFF | |
| 72 | + let tampered = VaultCrypto.VaultFile( | |
| 73 | + version: vault.version, kdf: vault.kdf, | |
| 74 | + cipher: vault.cipher, ciphertext: combined.base64EncodedString() | |
| 75 | + ) | |
| 76 | + XCTAssertThrowsError(try VaultCrypto.open(tampered, password: "pw")) | |
| 77 | + } | |
| 78 | + | |
| 79 | + func testKeyManagerVaultLifecycle() throws { | |
| 80 | + let url = tempVaultURL() | |
| 81 | + let manager = KeyManager(vaultURL: url) | |
| 82 | + XCTAssertFalse(manager.hasVault) | |
| 83 | + | |
| 84 | + let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" | |
| 85 | + let saved = try manager.saveWallet(mnemonic: mnemonic, password: "test-password-123") | |
| 86 | + XCTAssertTrue(manager.hasVault) | |
| 87 | + | |
| 88 | + let unlocked = try manager.unlock(password: "test-password-123") | |
| 89 | + XCTAssertEqual(unlocked.address, saved.address) | |
| 90 | + XCTAssertEqual(unlocked.mnemonic, mnemonic) | |
| 91 | + | |
| 92 | + XCTAssertThrowsError(try manager.unlock(password: "nope")) { error in | |
| 93 | + XCTAssertEqual(error as? WalletError, .wrongPassword) | |
| 94 | + } | |
| 95 | + | |
| 96 | + // Vault file on disk must never contain the mnemonic in clear. | |
| 97 | + let raw = try String(contentsOf: url, encoding: .utf8) | |
| 98 | + XCTAssertFalse(raw.contains("abandon")) | |
| 99 | + | |
| 100 | + try manager.deleteVault() | |
| 101 | + XCTAssertFalse(manager.hasVault) | |
| 102 | + } | |
| 103 | +} | |
| 104 | + | |
| 105 | +final class TokenAmountTests: XCTestCase { | |
| 106 | + | |
| 107 | + func testUSDCSixDecimals() { | |
| 108 | + XCTAssertEqual(TokenAmount.parse("1", decimals: 6), 1_000_000) | |
| 109 | + XCTAssertEqual(TokenAmount.parse("12.5", decimals: 6), 12_500_000) | |
| 110 | + XCTAssertEqual(TokenAmount.parse("0.000001", decimals: 6), 1) | |
| 111 | + XCTAssertEqual(TokenAmount.parse("1,25", decimals: 6), 1_250_000) | |
| 112 | + XCTAssertNil(TokenAmount.parse("0.0000001", decimals: 6)) // too many digits | |
| 113 | + XCTAssertNil(TokenAmount.parse("", decimals: 6)) | |
| 114 | + XCTAssertNil(TokenAmount.parse("1.2.3", decimals: 6)) | |
| 115 | + XCTAssertNil(TokenAmount.parse("abc", decimals: 6)) | |
| 116 | + XCTAssertNil(TokenAmount.parse("-1", decimals: 6)) | |
| 117 | + } | |
| 118 | + | |
| 119 | + func testDAIEighteenDecimals() { | |
| 120 | + XCTAssertEqual(TokenAmount.parse("1", decimals: 18), BigUInt(10).power(18)) | |
| 121 | + XCTAssertEqual(TokenAmount.format(BigUInt(10).power(18), decimals: 18), "1") | |
| 122 | + XCTAssertEqual(TokenAmount.format(BigUInt(1_500) * BigUInt(10).power(15), decimals: 18), "1.5") | |
| 123 | + } | |
| 124 | + | |
| 125 | + func testFormatting() { | |
| 126 | + XCTAssertEqual(TokenAmount.format(1_000_000, decimals: 6), "1") | |
| 127 | + XCTAssertEqual(TokenAmount.format(12_500_000, decimals: 6), "12.5") | |
| 128 | + XCTAssertEqual(TokenAmount.format(1, decimals: 6), "0.000001") | |
| 129 | + XCTAssertEqual(TokenAmount.format(0, decimals: 6), "0") | |
| 130 | + // Truncation, never rounding up. | |
| 131 | + XCTAssertEqual(TokenAmount.format(1_999_999, decimals: 6, maxFractionDigits: 2), "1.99") | |
| 132 | + } | |
| 133 | + | |
| 134 | + func testRoundtrip() { | |
| 135 | + let cases = ["0.1", "123456.654321", "1", "0.000001"] | |
| 136 | + for c in cases { | |
| 137 | + let parsed = TokenAmount.parse(c, decimals: 6)! | |
| 138 | + XCTAssertEqual(TokenAmount.format(parsed, decimals: 6), c) | |
| 139 | + } | |
| 140 | + } | |
| 141 | +} | |
| 142 | + | |
| 143 | +final class AddressValidationTests: XCTestCase { | |
| 144 | + | |
| 145 | + func testChecksummedAddressValid() { | |
| 146 | + // EIP-55 reference vectors. | |
| 147 | + let valid = [ | |
| 148 | + "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", | |
| 149 | + "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", | |
| 150 | + "0x52908400098527886E0F7030069857D2E4169EE7" | |
| 151 | + ] | |
| 152 | + for address in valid { | |
| 153 | + guard case .valid(let checksummed) = AddressValidator.validate(address) else { | |
| 154 | + return XCTFail("\(address) should be valid") | |
| 155 | + } | |
| 156 | + XCTAssertEqual(checksummed, address) | |
| 157 | + } | |
| 158 | + } | |
| 159 | + | |
| 160 | + func testBadChecksumInvalid() { | |
| 161 | + // One flipped case letter breaks the checksum. | |
| 162 | + XCTAssertEqual(AddressValidator.validate("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAeD"), .invalid) | |
| 163 | + } | |
| 164 | + | |
| 165 | + func testLowercaseWarnsButPasses() { | |
| 166 | + let result = AddressValidator.validate("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed") | |
| 167 | + guard case .validNoChecksum(let checksummed) = result else { | |
| 168 | + return XCTFail("lowercase should pass with warning") | |
| 169 | + } | |
| 170 | + XCTAssertEqual(checksummed, "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed") | |
| 171 | + } | |
| 172 | + | |
| 173 | + func testGarbageInvalid() { | |
| 174 | + XCTAssertEqual(AddressValidator.validate(""), .invalid) | |
| 175 | + XCTAssertEqual(AddressValidator.validate("0x123"), .invalid) | |
| 176 | + XCTAssertEqual(AddressValidator.validate("5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"), .invalid) | |
| 177 | + XCTAssertEqual(AddressValidator.validate("0xZZZeb6053F3E94C9b9A09f33669435E7Ef1BeAed"), .invalid) | |
| 178 | + } | |
| 179 | +} | |
| 180 | + | |
| 181 | +final class CalldataTests: XCTestCase { | |
| 182 | + | |
| 183 | + func testTransferCalldataShape() { | |
| 184 | + let recipient = "0x9858EfFD232B4033E47d90003D41EC34EcaEda94" | |
| 185 | + let calldata = Hex.erc20TransferData(to: recipient, amount: 1_000_000)! | |
| 186 | + XCTAssertEqual(calldata.count, 4 + 32 + 32) | |
| 187 | + XCTAssertEqual(calldata.prefix(4), Data([0xa9, 0x05, 0x9c, 0xbb])) | |
| 188 | + XCTAssertEqual(Hex.string(calldata.suffix(32)), | |
| 189 | + "0x00000000000000000000000000000000000000000000000000000000000f4240") | |
| 190 | + } | |
| 191 | + | |
| 192 | + func testBalanceOfCalldata() { | |
| 193 | + let owner = "0x9858EfFD232B4033E47d90003D41EC34EcaEda94" | |
| 194 | + let calldata = Hex.erc20BalanceOfData(owner: owner)! | |
| 195 | + XCTAssertEqual(calldata.count, 4 + 32) | |
| 196 | + XCTAssertEqual(calldata.prefix(4), Data([0x70, 0xa0, 0x82, 0x31])) | |
| 197 | + } | |
| 198 | + | |
| 199 | + func testQuantityHelpers() { | |
| 200 | + XCTAssertEqual(Hex.quantity(0), "0x0") | |
| 201 | + XCTAssertEqual(Hex.quantity(255), "0xff") | |
| 202 | + XCTAssertEqual(Hex.toBigUInt("0xff"), 255) | |
| 203 | + XCTAssertEqual(Hex.toBigUInt("0x"), 0) | |
| 204 | + XCTAssertNil(Hex.toBigUInt("0xzz")) | |
| 205 | + } | |
| 206 | +} | |
| 207 | + | |
| 208 | +func tempVaultURL() -> URL { | |
| 209 | + FileManager.default.temporaryDirectory | |
| 210 | + .appendingPathComponent("osvault-tests-\(UUID().uuidString)/vault.json") | |
| 211 | +} | |
added
Tests/OSVaultTests/SolanaTests.swift
+42 −0
@@ -0,0 +1,42 @@ | ||
| 1 | +// | |
| 2 | +// SolanaTests.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import XCTest | |
| 10 | +import SolanaSwift | |
| 11 | +@testable import OSVaultKit | |
| 12 | + | |
| 13 | +final class SolanaTests: XCTestCase { | |
| 14 | + | |
| 15 | + // Public BIP-44 test vector: the all-"abandon" mnemonic at | |
| 16 | + // m/44'/501'/0'/0' (bip44Change) — the Phantom/Solflare default. | |
| 17 | + let vectorMnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" | |
| 18 | + | |
| 19 | + func testDerivationIsDeterministicAndPhantomPath() async throws { | |
| 20 | + let first = try await SolanaService.deriveKeyPair(mnemonic: vectorMnemonic, network: .mainnet) | |
| 21 | + let second = try await SolanaService.deriveKeyPair(mnemonic: vectorMnemonic, network: .devnet) | |
| 22 | + // Cluster must not change the derivation; the keypair is path-only. | |
| 23 | + XCTAssertEqual(first.publicKey.base58EncodedString, second.publicKey.base58EncodedString) | |
| 24 | + XCTAssertEqual(first.secretKey.count, 64) | |
| 25 | + XCTAssertTrue(SolanaService.validate(address: first.publicKey.base58EncodedString)) | |
| 26 | + } | |
| 27 | + | |
| 28 | + func testAddressValidation() { | |
| 29 | + XCTAssertTrue(SolanaService.validate(address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")) | |
| 30 | + XCTAssertFalse(SolanaService.validate(address: "0x9858EfFD232B4033E47d90003D41EC34EcaEda94")) | |
| 31 | + XCTAssertFalse(SolanaService.validate(address: "not-an-address")) | |
| 32 | + XCTAssertFalse(SolanaService.validate(address: "")) | |
| 33 | + } | |
| 34 | + | |
| 35 | + func testAmountParsing() { | |
| 36 | + XCTAssertEqual(SolanaService.parseSOL("1"), 1_000_000_000) | |
| 37 | + XCTAssertEqual(SolanaService.parseSOL("0.000000001"), 1) | |
| 38 | + XCTAssertNil(SolanaService.parseSOL("0.0000000001")) // sub-lamport | |
| 39 | + XCTAssertEqual(SolanaService.parseUSDC("12.5"), 12_500_000) | |
| 40 | + XCTAssertEqual(SolanaService.formatSOL(1_500_000_000), "1.5") | |
| 41 | + } | |
| 42 | +} | |
added
Tests/OSVaultTests/WalletCoreTests.swift
+78 −0
@@ -0,0 +1,78 @@ | ||
| 1 | +// | |
| 2 | +// WalletCoreTests.swift | |
| 3 | +// OS Vault | |
| 4 | +// | |
| 5 | +// Author: Simon-Pierre Boucher | |
| 6 | +// Mail: contact@spboucher.ai | |
| 7 | +// | |
| 8 | + | |
| 9 | +import XCTest | |
| 10 | +import WalletCore | |
| 11 | +import Web3Core | |
| 12 | +@testable import OSVaultKit | |
| 13 | + | |
| 14 | +final class WalletCoreTests: XCTestCase { | |
| 15 | + | |
| 16 | + // Same public test vector as the rest of the suite. | |
| 17 | + let vectorMnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" | |
| 18 | + | |
| 19 | + func testEthereumAddressMatchesWeb3swift() throws { | |
| 20 | + // Cross-check the two independent secp256k1/BIP-32 stacks: wallet-core | |
| 21 | + // must derive the exact address web3swift derives (and the BIP-44 vector). | |
| 22 | + let hd = HDWallet(mnemonic: vectorMnemonic, passphrase: "")! | |
| 23 | + XCTAssertEqual(hd.getAddressForCoin(coin: .ethereum), | |
| 24 | + "0x9858EfFD232B4033E47d90003D41EC34EcaEda94") | |
| 25 | + } | |
| 26 | + | |
| 27 | + func testTronDerivationConsistentAcrossStacks() throws { | |
| 28 | + // Derive the Tron key with web3swift's HD stack at m/44'/195'/0'/0/0, | |
| 29 | + // feed the raw private key to wallet-core, and require the same | |
| 30 | + // address wallet-core derives internally from the mnemonic. | |
| 31 | + let hd = HDWallet(mnemonic: vectorMnemonic, passphrase: "")! | |
| 32 | + let fromMnemonic = hd.getAddressForCoin(coin: .tron) | |
| 33 | + | |
| 34 | + let seed = BIP39.seedFromMmemonics(vectorMnemonic, password: "", language: .english)! | |
| 35 | + let node = HDNode(seed: seed)!.derive(path: "m/44'/195'/0'/0/0", derivePrivateKey: true)! | |
| 36 | + let key = PrivateKey(data: node.privateKey!)! | |
| 37 | + let fromRawKey = CoinType.tron.deriveAddress(privateKey: key) | |
| 38 | + | |
| 39 | + XCTAssertEqual(fromMnemonic, fromRawKey) | |
| 40 | + XCTAssertTrue(fromMnemonic.hasPrefix("T")) | |
| 41 | + XCTAssertEqual(fromMnemonic.count, 34) | |
| 42 | + } | |
| 43 | + | |
| 44 | + func testXRPAndTONAddressesDerive() throws { | |
| 45 | + let hd = HDWallet(mnemonic: vectorMnemonic, passphrase: "")! | |
| 46 | + let xrp = hd.getAddressForCoin(coin: .xrp) | |
| 47 | + XCTAssertTrue(xrp.hasPrefix("r")) | |
| 48 | + let ton = hd.getAddressForCoin(coin: .ton) | |
| 49 | + XCTAssertTrue(ton.hasPrefix("UQ") || ton.hasPrefix("EQ")) | |
| 50 | + } | |
| 51 | + | |
| 52 | + func testTronAddressValidation() { | |
| 53 | + XCTAssertTrue(AnyAddress.isValid(string: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", coin: .tron)) | |
| 54 | + XCTAssertFalse(AnyAddress.isValid(string: "0x9858EfFD232B4033E47d90003D41EC34EcaEda94", coin: .tron)) | |
| 55 | + XCTAssertFalse(AnyAddress.isValid(string: "Tinvalid", coin: .tron)) | |
| 56 | + } | |
| 57 | +} | |
| 58 | + | |
| 59 | +final class XRPLTONTests: XCTestCase { | |
| 60 | + | |
| 61 | + func testXRPLValidationAndAmounts() { | |
| 62 | + XCTAssertTrue(XRPLService.validate(address: "rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De")) | |
| 63 | + XCTAssertFalse(XRPLService.validate(address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")) | |
| 64 | + XCTAssertEqual(XRPLService.parseXRP("1"), 1_000_000) | |
| 65 | + XCTAssertEqual(XRPLService.formatXRP(1_500_000), "1.5") | |
| 66 | + XCTAssertEqual(XRPLService.validRLUSDAmount("12,5"), "12.5") | |
| 67 | + XCTAssertNil(XRPLService.validRLUSDAmount("abc")) | |
| 68 | + XCTAssertNil(XRPLService.validRLUSDAmount("0")) | |
| 69 | + } | |
| 70 | + | |
| 71 | + func testTONValidationAndAmounts() { | |
| 72 | + XCTAssertTrue(TONService.validate(address: "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs")) | |
| 73 | + XCTAssertFalse(TONService.validate(address: "not-a-ton-address")) | |
| 74 | + XCTAssertEqual(TONService.parseTON("1"), 1_000_000_000) | |
| 75 | + XCTAssertEqual(TONService.parseUSDT("2.5"), 2_500_000) | |
| 76 | + XCTAssertEqual(TONService.formatTON(1_500_000_000), "1.5") | |
| 77 | + } | |
| 78 | +} | |
added
assets/icon/AppIcon.icns
+0 −0
Binary file not shown.
added
assets/icon/os-vault-simple.svg
+25 −0
@@ -0,0 +1,25 @@ | ||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + os-vault-simple.svg — OS Vault app icon, simplified variant baked at 16/32 px. | |
| 4 | + | |
| 5 | + Author: Simon-Pierre Boucher | |
| 6 | + Mail: contact@spboucher.ai | |
| 7 | +--> | |
| 8 | +<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"> | |
| 9 | + <defs> | |
| 10 | + <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"> | |
| 11 | + <stop offset="0" stop-color="#24355a"/> | |
| 12 | + <stop offset="1" stop-color="#0a1122"/> | |
| 13 | + </linearGradient> | |
| 14 | + </defs> | |
| 15 | + <rect x="64" y="64" width="896" height="896" rx="200" fill="url(#bg)"/> | |
| 16 | + <!-- bold wheel --> | |
| 17 | + <circle cx="512" cy="512" r="300" fill="none" stroke="#c9d3e2" stroke-width="96"/> | |
| 18 | + <g stroke="#c9d3e2" stroke-width="88" stroke-linecap="round"> | |
| 19 | + <line x1="512" y1="252" x2="512" y2="772"/> | |
| 20 | + <line x1="287" y1="382" x2="737" y2="642"/> | |
| 21 | + <line x1="737" y1="382" x2="287" y2="642"/> | |
| 22 | + </g> | |
| 23 | + <circle cx="512" cy="512" r="150" fill="#3ec3ff"/> | |
| 24 | + <circle cx="512" cy="512" r="150" fill="none" stroke="#0a1122" stroke-width="40"/> | |
| 25 | +</svg> | |
added
assets/icon/os-vault.svg
+158 −0
@@ -0,0 +1,158 @@ | ||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + os-vault.svg — OS Vault app icon (full detail, >= 64 px) | |
| 4 | + | |
| 5 | + Author: Simon-Pierre Boucher | |
| 6 | + Mail: contact@spboucher.ai | |
| 7 | + | |
| 8 | + Concept: a titanium vault door on a deep-space navy squircle, six-spoke | |
| 9 | + locking wheel, luminous cyan core with keyhole — self-custody, engineered | |
| 10 | + to feel unbreakable. | |
| 11 | +--> | |
| 12 | +<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"> | |
| 13 | + <defs> | |
| 14 | + <!-- background --> | |
| 15 | + <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"> | |
| 16 | + <stop offset="0" stop-color="#233457"/> | |
| 17 | + <stop offset="0.55" stop-color="#131d36"/> | |
| 18 | + <stop offset="1" stop-color="#080d1c"/> | |
| 19 | + </linearGradient> | |
| 20 | + <radialGradient id="bgGlow" cx="0.5" cy="0.28" r="0.75"> | |
| 21 | + <stop offset="0" stop-color="#3f6fd8" stop-opacity="0.45"/> | |
| 22 | + <stop offset="0.5" stop-color="#2a4a9e" stop-opacity="0.12"/> | |
| 23 | + <stop offset="1" stop-color="#000000" stop-opacity="0"/> | |
| 24 | + </radialGradient> | |
| 25 | + | |
| 26 | + <!-- metals --> | |
| 27 | + <linearGradient id="steel" x1="0" y1="0" x2="0" y2="1"> | |
| 28 | + <stop offset="0" stop-color="#f2f6fb"/> | |
| 29 | + <stop offset="0.35" stop-color="#c3ccd9"/> | |
| 30 | + <stop offset="0.7" stop-color="#8e9aac"/> | |
| 31 | + <stop offset="1" stop-color="#6a7689"/> | |
| 32 | + </linearGradient> | |
| 33 | + <linearGradient id="steelDeep" x1="0" y1="0" x2="0" y2="1"> | |
| 34 | + <stop offset="0" stop-color="#39445c"/> | |
| 35 | + <stop offset="0.5" stop-color="#232c42"/> | |
| 36 | + <stop offset="1" stop-color="#161d30"/> | |
| 37 | + </linearGradient> | |
| 38 | + <linearGradient id="steelRim" x1="0" y1="1" x2="0" y2="0"> | |
| 39 | + <stop offset="0" stop-color="#f0f4fa"/> | |
| 40 | + <stop offset="0.5" stop-color="#aab4c4"/> | |
| 41 | + <stop offset="1" stop-color="#78849a"/> | |
| 42 | + </linearGradient> | |
| 43 | + <linearGradient id="spoke" x1="0" y1="0" x2="0" y2="1"> | |
| 44 | + <stop offset="0" stop-color="#eef2f8"/> | |
| 45 | + <stop offset="0.5" stop-color="#b5bfce"/> | |
| 46 | + <stop offset="1" stop-color="#7f8ba0"/> | |
| 47 | + </linearGradient> | |
| 48 | + | |
| 49 | + <!-- accent core --> | |
| 50 | + <radialGradient id="core" cx="0.5" cy="0.42" r="0.7"> | |
| 51 | + <stop offset="0" stop-color="#9be8ff"/> | |
| 52 | + <stop offset="0.45" stop-color="#3ec3ff"/> | |
| 53 | + <stop offset="0.8" stop-color="#1470e0"/> | |
| 54 | + <stop offset="1" stop-color="#0b4bb0"/> | |
| 55 | + </radialGradient> | |
| 56 | + <radialGradient id="coreHalo" cx="0.5" cy="0.5" r="0.5"> | |
| 57 | + <stop offset="0.55" stop-color="#3ec3ff" stop-opacity="0"/> | |
| 58 | + <stop offset="0.8" stop-color="#3ec3ff" stop-opacity="0.35"/> | |
| 59 | + <stop offset="1" stop-color="#3ec3ff" stop-opacity="0"/> | |
| 60 | + </radialGradient> | |
| 61 | + | |
| 62 | + <filter id="doorShadow" x="-30%" y="-30%" width="160%" height="160%"> | |
| 63 | + <feDropShadow dx="0" dy="26" stdDeviation="34" flood-color="#000000" flood-opacity="0.55"/> | |
| 64 | + </filter> | |
| 65 | + <filter id="lift" x="-40%" y="-40%" width="180%" height="180%"> | |
| 66 | + <feDropShadow dx="0" dy="8" stdDeviation="10" flood-color="#000000" flood-opacity="0.45"/> | |
| 67 | + </filter> | |
| 68 | + | |
| 69 | + <clipPath id="squircle"> | |
| 70 | + <rect x="96" y="96" width="832" height="832" rx="186"/> | |
| 71 | + </clipPath> | |
| 72 | + </defs> | |
| 73 | + | |
| 74 | + <!-- squircle plate --> | |
| 75 | + <g> | |
| 76 | + <rect x="96" y="96" width="832" height="832" rx="186" fill="url(#bg)"/> | |
| 77 | + <g clip-path="url(#squircle)"> | |
| 78 | + <rect x="96" y="96" width="832" height="832" fill="url(#bgGlow)"/> | |
| 79 | + <!-- engraved corner braces --> | |
| 80 | + <g stroke="#5f79b3" stroke-opacity="0.28" stroke-width="10" fill="none"> | |
| 81 | + <path d="M158 300 v-70 a72 72 0 0 1 72 -72 h70"/> | |
| 82 | + <path d="M866 300 v-70 a72 72 0 0 0 -72 -72 h-70"/> | |
| 83 | + <path d="M158 724 v70 a72 72 0 0 0 72 72 h70"/> | |
| 84 | + <path d="M866 724 v70 a72 72 0 0 1 -72 72 h-70"/> | |
| 85 | + </g> | |
| 86 | + <!-- inner bevel of the plate --> | |
| 87 | + <rect x="110" y="110" width="804" height="804" rx="174" fill="none" | |
| 88 | + stroke="#8fb0ff" stroke-opacity="0.16" stroke-width="4"/> | |
| 89 | + </g> | |
| 90 | + </g> | |
| 91 | + | |
| 92 | + <!-- vault door --> | |
| 93 | + <g filter="url(#doorShadow)"> | |
| 94 | + <circle cx="512" cy="512" r="308" fill="url(#steelRim)"/> | |
| 95 | + <circle cx="512" cy="512" r="308" fill="none" stroke="#101624" stroke-opacity="0.55" stroke-width="3"/> | |
| 96 | + </g> | |
| 97 | + <!-- recessed track --> | |
| 98 | + <circle cx="512" cy="512" r="262" fill="url(#steelDeep)"/> | |
| 99 | + <circle cx="512" cy="512" r="262" fill="none" stroke="#0a0f1c" stroke-width="6" stroke-opacity="0.7"/> | |
| 100 | + <circle cx="512" cy="512" r="240" fill="none" stroke="#9fc6ff" stroke-opacity="0.14" stroke-width="3"/> | |
| 101 | + | |
| 102 | + <!-- rim bolts --> | |
| 103 | + <g fill="url(#steel)" stroke="#141a29" stroke-width="3"> | |
| 104 | + <circle cx="512" cy="228" r="17"/> | |
| 105 | + <circle cx="712.8" cy="311.2" r="17"/> | |
| 106 | + <circle cx="796" cy="512" r="17"/> | |
| 107 | + <circle cx="712.8" cy="712.8" r="17"/> | |
| 108 | + <circle cx="512" cy="796" r="17"/> | |
| 109 | + <circle cx="311.2" cy="712.8" r="17"/> | |
| 110 | + <circle cx="228" cy="512" r="17"/> | |
| 111 | + <circle cx="311.2" cy="311.2" r="17"/> | |
| 112 | + </g> | |
| 113 | + | |
| 114 | + <!-- locking wheel: six spokes --> | |
| 115 | + <g filter="url(#lift)"> | |
| 116 | + <g fill="url(#spoke)" stroke="#1a2233" stroke-width="4"> | |
| 117 | + <g transform="rotate(0 512 512)"> | |
| 118 | + <rect x="492" y="292" width="40" height="440" rx="20"/> | |
| 119 | + </g> | |
| 120 | + <g transform="rotate(60 512 512)"> | |
| 121 | + <rect x="492" y="292" width="40" height="440" rx="20"/> | |
| 122 | + </g> | |
| 123 | + <g transform="rotate(120 512 512)"> | |
| 124 | + <rect x="492" y="292" width="40" height="440" rx="20"/> | |
| 125 | + </g> | |
| 126 | + </g> | |
| 127 | + <!-- wheel outer ring --> | |
| 128 | + <circle cx="512" cy="512" r="220" fill="none" stroke="url(#steel)" stroke-width="42"/> | |
| 129 | + <circle cx="512" cy="512" r="242" fill="none" stroke="#0d1220" stroke-opacity="0.6" stroke-width="4"/> | |
| 130 | + <circle cx="512" cy="512" r="199" fill="none" stroke="#0d1220" stroke-opacity="0.6" stroke-width="4"/> | |
| 131 | + <!-- spoke grips --> | |
| 132 | + <g fill="url(#steel)" stroke="#141a29" stroke-width="4"> | |
| 133 | + <circle cx="512" cy="292" r="34"/> | |
| 134 | + <circle cx="702.5" cy="622" r="34"/> | |
| 135 | + <circle cx="321.5" cy="622" r="34"/> | |
| 136 | + <circle cx="512" cy="732" r="34"/> | |
| 137 | + <circle cx="321.5" cy="402" r="34"/> | |
| 138 | + <circle cx="702.5" cy="402" r="34"/> | |
| 139 | + </g> | |
| 140 | + </g> | |
| 141 | + | |
| 142 | + <!-- luminous core hub --> | |
| 143 | + <circle cx="512" cy="512" r="150" fill="url(#coreHalo)"/> | |
| 144 | + <g filter="url(#lift)"> | |
| 145 | + <circle cx="512" cy="512" r="112" fill="url(#steel)"/> | |
| 146 | + <circle cx="512" cy="512" r="112" fill="none" stroke="#10162a" stroke-width="4"/> | |
| 147 | + </g> | |
| 148 | + <circle cx="512" cy="512" r="88" fill="url(#core)"/> | |
| 149 | + <circle cx="512" cy="512" r="88" fill="none" stroke="#062a66" stroke-width="5"/> | |
| 150 | + <!-- keyhole --> | |
| 151 | + <g fill="#04122e"> | |
| 152 | + <circle cx="512" cy="488" r="26"/> | |
| 153 | + <path d="M496 500 L528 500 L540 566 A10 10 0 0 1 530 576 L494 576 A10 10 0 0 1 484 566 Z"/> | |
| 154 | + </g> | |
| 155 | + <!-- specular sweep on the door --> | |
| 156 | + <path d="M254 388 A 300 300 0 0 1 770 388 A 380 380 0 0 0 254 388 Z" | |
| 157 | + fill="#ffffff" opacity="0.10"/> | |
| 158 | +</svg> | |
added
docs/RESEARCH-MULTICHAIN.md
+93 −0
@@ -0,0 +1,93 @@ | ||
| 1 | +<!-- | |
| 2 | + RESEARCH-MULTICHAIN.md | |
| 3 | + OS Vault | |
| 4 | + | |
| 5 | + Author: Simon-Pierre Boucher | |
| 6 | + Mail: contact@spboucher.ai | |
| 7 | +--> | |
| 8 | + | |
| 9 | +# Multi-chain implementation research — synthesis (2026-08-05) | |
| 10 | + | |
| 11 | +Five parallel research tracks (wallet-core/architecture, Bitcoin, non-EVM | |
| 12 | +chains, EVM expansion, keyless infra), all endpoint/address claims **verified | |
| 13 | +live** during research. This file is the implementation blueprint; statuses | |
| 14 | +below reflect what is already shipped in the code. | |
| 15 | + | |
| 16 | +## Verdicts at a glance | |
| 17 | + | |
| 18 | +| Track | Verdict | Status in OS Vault | | |
| 19 | +|---|---|---| | |
| 20 | +| EVM multichain | Data-driven: 11 chains, 4 real fee models, PublicNode primary keyless RPC + failover | ✅ **Implemented** (`Network.swift`, `TransactionService.swift`) | | |
| 21 | +| Native coin send | Always `eth_estimateGas` (never 21000); OP-stack/Scroll L1 data fee via oracle | ✅ **Implemented** | | |
| 22 | +| Stablecoin matrix | Verified per-chain addresses; BNB peg = 18 decimals; USDC.e ≠ USDC by address only | ✅ **Implemented** (`Token.swift`) | | |
| 23 | +| Bitcoin | **bdk-swift 3.0.0** — only maintained macOS+SPM option; BIP-84; keyless Esplora (mempool.space) | ✅ **Implemented** (`BitcoinService.swift`, watch-only + transient signer) | | |
| 24 | +| Fiat prices | CoinGecko keyless batched (`/simple/price`, USD/CAD/EUR); DefiLlama fallback; prices-OFF mode | ✅ **Implemented** (`PriceService.swift`) | | |
| 25 | +| wallet-core (Tron/TON/XRPL signing) | Vendored at `vendor/WalletCoreSPM` (binaryTarget; duplicate Rust `_rust_eh_personality` vs bdkFFI demoted surgically in the archive — see vendor script) | ✅ **Vendored + tested** (ETH vector, Tron cross-stack, XRP/TON derive) | | |
| 26 | +| Solana | `p2p-org/solana-swift` vendored (`vendor/solana-swift` — its Boilertalk secp256k1 dep clashed with web3swift's target name; CKSecp256k1 re-backed by Web3Core); PublicNode RPC keyless; ATA rent surfaced pre-send | ✅ **Implemented** (`SolanaService.swift`, SOL + USDC, devnet default) | | |
| 27 | +| Tron | wallet-core `TransferContract`/`TransferTRC20Contract` + TronGrid keyless; energy burn estimated pre-send via `triggerconstantcontract`, fee_limit 100 TRX; Nile default (USDT `TXYZ…AeBf` verified live) | ✅ **Implemented** (`TronService.swift`) | | |
| 28 | +| TON | tonkeeper/ton-swift + toncenter (1 req/s keyless); jetton indirection; BIP-39 path m/44'/607' (Tonkeeper won't import directly — document) | ⏭ Next | | |
| 29 | +| XRPL | wallet-core signer (TrustSet + issued currencies = RLUSD); xrplcluster.com genuinely free; 1 XRP base reserve + 0.2/trustline | ⏭ Next | | |
| 30 | +| Stellar | Soneso stellar-ios-mac-sdk — best non-EVM Swift SDK, nearly free to add | ⏭ Bonus | | |
| 31 | +| History indexing | No keyless multi-chain indexer exists. Per chain: Blockscout v2 (7 EVM chains), Routescan (Avalanche/Mantle/Blast), mempool.space (BTC), else eth_getLogs incremental. BNB/Linea = optional user key | ⏭ Next | | |
| 32 | +| Fiat FX | Frankfurter (ECB, keyless, unlimited); avoid exchangerate.host (keyed now) | Covered via CoinGecko native CAD/EUR | | |
| 33 | +| Auto-update | Sparkle 2 via SPM, EdDSA + notarization, static appcast on GitHub Releases | ⏭ When distribution starts | | |
| 34 | + | |
| 35 | +## Key implementation facts (already coded) | |
| 36 | + | |
| 37 | +- **Fee models** (`Network.FeeModel`): `eip1559` · `zeroBaseFee` (BSC/BEP-226: | |
| 38 | + price via `eth_gasPrice`) · `opStackL1Fee` (Base/OP: add | |
| 39 | + `GasPriceOracle.getL1Fee(unsigned tx)` at `0x42…0F` to the confirm total) · | |
| 40 | + `scrollL1Fee` (oracle `0x5300…0002`) · `arbitrumInclusive` (estimate already | |
| 41 | + includes L1 buffer, tip 0, use verbatim) · `lineaPinnedBase` (base pinned at | |
| 42 | + 7 wei, cost rides in the tip). | |
| 43 | +- **RPC failover** (`RPCService`): ordered keyless endpoints per chain | |
| 44 | + (PublicNode primary — all 11 verified; official RPC fallback), sticky | |
| 45 | + primary, 60 s demotion cooldown, node-side errors surface immediately. | |
| 46 | + Dead/keyed providers found in research: llamarpc (521), Ankr (key now), | |
| 47 | + 1rpc (quota), polygon-rpc.com (401 intermittent). | |
| 48 | +- **Registry traps**: BNB USDT/USDC are 18 decimals (separate Token entries); | |
| 49 | + USDC.e shares `symbol()` with native USDC on Arb/OP/Polygon (distinguish by | |
| 50 | + address, display "USDC.e"); Arbitrum/Polygon USDT upgraded in place to USDT0 | |
| 51 | + (same address/decimals — never assert symbol strings); Gnosis native xDAI is | |
| 52 | + itself dollar-pegged. | |
| 53 | +- **Bitcoin** (`BitcoinService`): BIP-84 descriptors from the same vault | |
| 54 | + mnemonic (BIP-84 spec vector unit-tested); watch-only persisted wallet | |
| 55 | + (public descriptors, BDK SQLite) for sync/balance/receive with address | |
| 56 | + rotation; sends build the PSBT on the watch wallet, then a throwaway | |
| 57 | + in-memory signer wallet (secret descriptors re-derived from the password) | |
| 58 | + signs and is discarded. Esplora keyless: mempool.space (+ blockstream.info | |
| 59 | + broadcast fallback on mainnet); fees from `/api/v1/fees/recommended`. | |
| 60 | + Default network **signet** (testnet-first), mainnet behind the switch. | |
| 61 | +- **Prices** (`PriceService`): one batched CoinGecko call for every asset × | |
| 62 | + USD/CAD/EUR at ≥120 s TTL (≈0.5 calls/min vs 5–15/min keyless budget); | |
| 63 | + stale-while-revalidate JSON cache; Settings toggle removes the only | |
| 64 | + non-blockchain egress. CoinCap and CryptoCompare are dead as keyless | |
| 65 | + options; Binance geoblocks; Coinbase spot is the per-pair fallback. | |
| 66 | + | |
| 67 | +## wallet-core vendoring (next phase enabler) | |
| 68 | + | |
| 69 | +Upstream declined macOS SPM support (PR #3529), but the **official CocoaPods | |
| 70 | +tarball** (`TrustWalletCore-<v>.tar.xz` on GitHub releases) contains | |
| 71 | +`WalletCoreCommon.xcframework` with a `macos-arm64_x86_64` slice plus the | |
| 72 | +Swift wrappers. `scripts/vendor-walletcore.sh` automates: download → verify → | |
| 73 | +C-headers target (incl. the **security-critical `SecRandom.m`** RNG shim) → | |
| 74 | +sed module imports → local SPM package in `vendor/WalletCoreSPM`. Proven by a | |
| 75 | +local build that derived BTC/ETH/Solana/Tron/TON/XRP addresses from one | |
| 76 | +runtime mnemonic. Cost: ~33 MB binary. One library then signs every remaining | |
| 77 | +chain (Tron `TransferTRC20Contract`, TON `JettonTransfer` + wallet v5R1, XRPL | |
| 78 | +`TrustSet`/issued currencies, Solana `CreateAndTransferToken`). | |
| 79 | + | |
| 80 | +## Non-EVM priority order (stablecoin volume × cost) | |
| 81 | + | |
| 82 | +1. **Solana / USDC** — cheapest build (solana-swift is macOS-native) and top | |
| 83 | + USDC venue; pipe-cleaner for the adapter pattern. | |
| 84 | +2. **Tron / USDT-TRC20** — largest USDT corridor on earth; energy-fee UX is | |
| 85 | + the main work (estimate via `triggerconstantcontract`, `fee_limit` 100 TRX). | |
| 86 | +3. **TON / USDT jetton** — jetton-wallet indirection, 1 rps toncenter queue. | |
| 87 | +4. **XRPL / RLUSD + XRP** — trustline UX (one-tap TrustSet, check recipient | |
| 88 | + `account_lines` pre-send), reserves surfaced as non-spendable. | |
| 89 | +5. **Stellar / USDC** — Soneso SDK, trustlines like XRPL, nearly free to add. | |
| 90 | + | |
| 91 | +Full per-chain details (curves, derivation paths, endpoints, faucets, rate | |
| 92 | +limits, sources) live in the research transcripts; the numbers used in code | |
| 93 | +are restated in comments at their point of use. | |
added
docs/ROADMAP.md
+65 −0
@@ -0,0 +1,65 @@ | ||
| 1 | +<!-- | |
| 2 | + ROADMAP.md | |
| 3 | + OS Vault | |
| 4 | + | |
| 5 | + Author: Simon-Pierre Boucher | |
| 6 | + Mail: contact@spboucher.ai | |
| 7 | +--> | |
| 8 | + | |
| 9 | +# OS Vault — Multi-chain / multi-stablecoin roadmap | |
| 10 | + | |
| 11 | +v1 is Base-only (Sepolia default, mainnet behind the network switch) with a | |
| 12 | +data-driven token registry (USDC default + EURC, DAI, USDT). The goal is broad | |
| 13 | +stablecoin coverage across chains. Target matrix (user-provided, 2026-08-05): | |
| 14 | + | |
| 15 | +| Stablecoin | Main chains | | |
| 16 | +|---|---| | |
| 17 | +| USDT | Ethereum, Tron, Solana, BNB Chain, Avalanche, Arbitrum, Optimism, Polygon, TON, Aptos, Celo, EOS, Near, Tezos, Algorand, Cosmos (Noble), Kaia, Ink… | | |
| 18 | +| USDC | Ethereum, Solana, Base, Arbitrum, Optimism, Polygon, Avalanche, Stellar, Aptos, Sui, Hedera, Algorand, Celo, Near, ZKsync, Starknet, Linea, Monad, XRP Ledger, World Chain, Unichain, XDC, Sei, Sonic, Polkadot, Morph, Ink, HyperEVM, Noble… (30+ networks) | | |
| 19 | +| USDe | Ethereum, Solana, BNB Chain, Base, Arbitrum, Optimism, Mantle, Scroll | | |
| 20 | +| DAI / USDS | Ethereum, Arbitrum, Optimism, Base, Polygon, Avalanche, BNB Chain, Gnosis, Linea, Scroll, Unichain | | |
| 21 | +| FDUSD | Ethereum, BNB Chain | | |
| 22 | +| USDB | Blast, Ethereum | | |
| 23 | +| PYUSD | Ethereum, Solana | | |
| 24 | +| RLUSD | XRP Ledger, Ethereum | | |
| 25 | +| USDG | Ethereum, Solana, Ink | | |
| 26 | +| TUSD | Ethereum, Tron, BNB Chain, Avalanche | | |
| 27 | + | |
| 28 | +> **Status 2026-08-05**: Phase A is **shipped** (11 EVM chains, verified token | |
| 29 | +> matrix, fee models incl. L1 data fees, keyless RPC failover, native coin | |
| 30 | +> sends) plus **Bitcoin** (bdk-swift, BIP-84, keyless Esplora) and fiat prices | |
| 31 | +> (CoinGecko keyless). Non-EVM adapters are next — see | |
| 32 | +> docs/RESEARCH-MULTICHAIN.md for the full blueprint and the wallet-core | |
| 33 | +> vendoring path (`scripts/vendor-walletcore.sh`). | |
| 34 | + | |
| 35 | +## Phase A — EVM expansion (cheap: registry entries, no new signer) | |
| 36 | + | |
| 37 | +Every EVM chain reuses the existing stack unchanged: secp256k1 keys at | |
| 38 | +m/44'/60'/0'/0/0, EIP-1559 signing, JSON-RPC, ERC-20 calldata. Adding | |
| 39 | +Ethereum/Arbitrum/Optimism/Polygon/BNB/Avalanche/Scroll/Linea/Gnosis/Blast… = | |
| 40 | +new `Network.ChainConfig` entries (chain id, RPC, explorer) + token addresses | |
| 41 | +in the registry, each verified on-chain before shipping (decimals() + symbol() | |
| 42 | +eth_call), exactly like docs/STABLECOINS.md. Watch out for: legacy-fee chains | |
| 43 | +(BNB has no EIP-1559 → needs type-0 path), native-gas symbol per chain | |
| 44 | +(POL, AVAX, BNB…), and chains where USDT is non-standard ERC-20 (no return | |
| 45 | +value — fine, we don't use the return value). | |
| 46 | + | |
| 47 | +## Phase B — Non-EVM chains (new signers, per-family adapters) | |
| 48 | + | |
| 49 | +Each family is a `ChainAdapter` implementation (derivation path, address | |
| 50 | +format, tx builder, RPC protocol): | |
| 51 | + | |
| 52 | +- **Solana** (USDC, USDT, PYUSD, USDe, USDG): ed25519 keys (m/44'/501'/…), | |
| 53 | + SPL-token transfers, its own RPC. Biggest payoff after EVM. | |
| 54 | +- **Tron** (huge USDT volume): secp256k1 but base58 addresses + TRC-20. | |
| 55 | +- **XRPL** (RLUSD), **Stellar** (USDC), **TON**, **Aptos/Sui**, **Noble/Cosmos**: | |
| 56 | + one adapter each, prioritized by user demand. | |
| 57 | + | |
| 58 | +The vault format already supports this: one mnemonic → per-chain derivation, | |
| 59 | +`VaultPayload.derivationPath` becomes a per-adapter map. | |
| 60 | + | |
| 61 | +## Phase C — polish | |
| 62 | + | |
| 63 | +- On-chain history via explorer APIs per chain (graceful fallback). | |
| 64 | +- Fiat (USD/CAD/EUR) valuation of balances, price feed optional & privacy-safe. | |
| 65 | +- Address book, per-token hide/show, Ledger-style hardware signing. | |
added
docs/STABLECOINS.md
+94 −0
@@ -0,0 +1,94 @@ | ||
| 1 | +<!-- | |
| 2 | + STABLECOINS.md | |
| 3 | + OS Vault | |
| 4 | + | |
| 5 | + Author: Simon-Pierre Boucher | |
| 6 | + Mail: contact@spboucher.ai | |
| 7 | +--> | |
| 8 | + | |
| 9 | +# How USDC and other stablecoins work (on Base) | |
| 10 | + | |
| 11 | +Written before implementation, per project rule: *understand the asset before building the wallet.* | |
| 12 | +Every address and decimal count below was **verified live on-chain on 2026-08-05** via | |
| 13 | +`eth_call` against `https://mainnet.base.org` / `https://sepolia.base.org` and the | |
| 14 | +Etherscan contract-source API — not taken from memory. | |
| 15 | + | |
| 16 | +## 1. What a stablecoin is, mechanically | |
| 17 | + | |
| 18 | +A stablecoin like USDC is **not a native blockchain asset**. It is an entry in the | |
| 19 | +storage of an **ERC-20 smart contract**. "Holding 10 USDC" means the USDC contract's | |
| 20 | +internal `balances[yourAddress]` equals `10_000_000` (10 × 10⁶ base units). | |
| 21 | + | |
| 22 | +Consequences for a wallet: | |
| 23 | + | |
| 24 | +- **Balances** are read with `balanceOf(address)` (an `eth_call`, selector `0x70a08231`), | |
| 25 | + not `eth_getBalance` (which returns native ETH). | |
| 26 | +- **Transfers** are transactions **to the token contract**, with calldata | |
| 27 | + `transfer(to, amount)` (selector `0xa9059cbb`), `value = 0`. The recipient address | |
| 28 | + lives inside the calldata, not in the tx `to` field. | |
| 29 | +- **Gas is always paid in ETH**, never in the stablecoin. A wallet full of USDC with | |
| 30 | + 0 ETH cannot move — the UI must surface this before the user hits a failed send. | |
| 31 | +- Incoming/outgoing movements are observed via the contract's `Transfer(from, to, value)` | |
| 32 | + event logs, which is what explorers index for token history. | |
| 33 | + | |
| 34 | +## 2. Issuance models (why "stable") | |
| 35 | + | |
| 36 | +| Model | Example | Peg mechanism | Trust assumption | | |
| 37 | +|---|---|---|---| | |
| 38 | +| Fiat-backed, centralized | **USDC, EURC** (Circle), **USDT** (Tether) | 1:1 reserves (cash + T-bills); mint/burn on deposit/redemption | Issuer solvency + banking rails | | |
| 39 | +| Crypto-collateralized | **DAI** (MakerDAO/Sky) | Overcollateralized vaults + rates | Protocol governance + collateral quality | | |
| 40 | +| Bridged representation | **USDbC** (Base) | Lock on L1, mint wrapped on L2 | The bridge, **plus** the original issuer | | |
| 41 | + | |
| 42 | +Key operational facts for fiat-backed coins (USDC family): | |
| 43 | + | |
| 44 | +- The contract is an **upgradeable proxy**. Verified: Base USDC is Circle's | |
| 45 | + `FiatTokenProxy` (AdminUpgradeabilityProxy pattern, implementation at | |
| 46 | + `0x2ce6311ddae708829bc0784c967b7d77d19fd779`, upgradeable by Circle's admin key). | |
| 47 | + Behavior can change under the same address — one more reason a wallet should treat | |
| 48 | + token metadata (decimals) as per-token config, verified on-chain, not assumptions. | |
| 49 | +- The issuer can **blocklist addresses** (`blacklist(address)` in FiatToken). Funds at a | |
| 50 | + blocklisted address are frozen at the contract level. Self-custody protects keys, not | |
| 51 | + against issuer-level freezing — worth knowing, nothing for the wallet to implement. | |
| 52 | +- Some support gasless-approval extensions (EIP-2612 `permit`, EIP-3009 | |
| 53 | + `transferWithAuthorization`). v1 uses plain `transfer` only. | |
| 54 | + | |
| 55 | +## 3. Decimals — the #1 bug source (verified live) | |
| 56 | + | |
| 57 | +**Decimals differ per token.** A wallet must never hardcode 6. | |
| 58 | + | |
| 59 | +| Token | Base mainnet address (chain 8453) | Decimals | Notes | | |
| 60 | +|---|---|---|---| | |
| 61 | +| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | **6** | Native Circle issue — the default token | | |
| 62 | +| EURC | `0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42` | **6** | Circle euro coin | | |
| 63 | +| USDT | `0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2` | **6** | Tether on Base | | |
| 64 | +| DAI | `0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb` | **18** | ⚠ 18, like ETH — not 6 | | |
| 65 | +| USDbC | `0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA` | **6** | Legacy bridged USDC; receive/display only, discourage new use | | |
| 66 | + | |
| 67 | +Testnet (Base Sepolia, chain 84532): USDC `0x036CbD53842c5426634e7929541eC2318f3dCF7e`, | |
| 68 | +decimals **6** (verified). Circle faucet: https://faucet.circle.com (20 USDC / 2 h); | |
| 69 | +gas ETH from a Base Sepolia faucet. | |
| 70 | + | |
| 71 | +Rules the code enforces: | |
| 72 | +- All amounts are `BigUInt` base units internally; `Double` is banned for money. | |
| 73 | +- Conversion display ⇄ base units goes through per-token `decimals` from the registry | |
| 74 | + (`TokenAmount`), unit-tested for 6- and 18-decimal tokens. | |
| 75 | +- ETH (gas) is 18 decimals; wei ⇄ ETH uses the same integer math. | |
| 76 | + | |
| 77 | +## 4. Chain facts (verified live) | |
| 78 | + | |
| 79 | +- Base mainnet `eth_chainId` → `0x2105` = **8453**; Base Sepolia → `0x14a34` = **84532**. | |
| 80 | +- Base is an OP-stack L2: EIP-1559 fees (`maxFeePerGas` / `maxPriorityFeePerGas`), | |
| 81 | + tips are tiny (fractions of a gwei), an ERC-20 transfer costs well under a cent. | |
| 82 | +- The signed transaction embeds the chain ID (EIP-155/1559) — replay protection across | |
| 83 | + Sepolia/mainnet is automatic as long as the wallet signs with the selected network's ID. | |
| 84 | + | |
| 85 | +## 5. What this means for OS Vault's design | |
| 86 | + | |
| 87 | +- A **token registry** (`Token` model) instead of a hardcoded USDC constant: symbol, | |
| 88 | + name, per-network contract address, decimals. v1 ships USDC as default with EURC, | |
| 89 | + DAI, USDT registered; adding a stablecoin is a registry entry, not a code change. | |
| 90 | +- Per-token balance = one `eth_call` each; ETH balance fetched alongside for the gas | |
| 91 | + warning ("not enough ETH to send"). | |
| 92 | +- Send flow is token-generic: encode `transfer(to, amount)` with the token's address | |
| 93 | + and decimals; everything else (nonce, fees, signing, receipt polling) is identical | |
| 94 | + across stablecoins. | |
added
scripts/make-icon.sh
+36 −0
@@ -0,0 +1,36 @@ | ||
| 1 | +#!/bin/bash | |
| 2 | +# | |
| 3 | +# make-icon.sh | |
| 4 | +# OS Vault | |
| 5 | +# | |
| 6 | +# Author: Simon-Pierre Boucher | |
| 7 | +# Mail: contact@spboucher.ai | |
| 8 | +# | |
| 9 | +# SVG → AppIcon.icns. Full-detail SVG for ≥64 px, simplified variant for 16/32 px. | |
| 10 | + | |
| 11 | +set -euo pipefail | |
| 12 | +cd "$(dirname "$0")/../assets/icon" | |
| 13 | + | |
| 14 | +RSVG=rsvg-convert | |
| 15 | +command -v $RSVG >/dev/null || { echo "rsvg-convert not found (brew install librsvg)"; exit 1; } | |
| 16 | + | |
| 17 | +ICONSET=AppIcon.iconset | |
| 18 | +rm -rf "$ICONSET" && mkdir "$ICONSET" | |
| 19 | + | |
| 20 | +# 16/32 from the simplified variant (16@2x = 32 px also simplified) | |
| 21 | +$RSVG -w 16 -h 16 os-vault-simple.svg -o "$ICONSET/icon_16x16.png" | |
| 22 | +$RSVG -w 32 -h 32 os-vault-simple.svg -o "$ICONSET/icon_16x16@2x.png" | |
| 23 | +$RSVG -w 32 -h 32 os-vault-simple.svg -o "$ICONSET/icon_32x32.png" | |
| 24 | +# ≥64 from the full-detail icon | |
| 25 | +$RSVG -w 64 -h 64 os-vault.svg -o "$ICONSET/icon_32x32@2x.png" | |
| 26 | +$RSVG -w 128 -h 128 os-vault.svg -o "$ICONSET/icon_128x128.png" | |
| 27 | +$RSVG -w 256 -h 256 os-vault.svg -o "$ICONSET/icon_128x128@2x.png" | |
| 28 | +$RSVG -w 256 -h 256 os-vault.svg -o "$ICONSET/icon_256x256.png" | |
| 29 | +$RSVG -w 512 -h 512 os-vault.svg -o "$ICONSET/icon_256x256@2x.png" | |
| 30 | +$RSVG -w 512 -h 512 os-vault.svg -o "$ICONSET/icon_512x512.png" | |
| 31 | +$RSVG -w 1024 -h 1024 os-vault.svg -o "$ICONSET/icon_512x512@2x.png" | |
| 32 | + | |
| 33 | +iconutil -c icns "$ICONSET" -o AppIcon.icns | |
| 34 | +rm -rf "$ICONSET" | |
| 35 | + | |
| 36 | +echo "AppIcon.icns generated." | |
added
scripts/release.sh
+84 −0
@@ -0,0 +1,84 @@ | ||
| 1 | +#!/bin/bash | |
| 2 | +# | |
| 3 | +# release.sh | |
| 4 | +# OS Vault | |
| 5 | +# | |
| 6 | +# Author: Simon-Pierre Boucher | |
| 7 | +# Mail: contact@spboucher.ai | |
| 8 | +# | |
| 9 | +# Developer ID signing, notarization and stapling for OS Vault. | |
| 10 | +# Identity and notarytool profile reused from the Zyquo Local/Term pipeline. | |
| 11 | +# | |
| 12 | +# Usage: | |
| 13 | +# scripts/release.sh # full: build + bundle + sign + notarize + staple + dmg | |
| 14 | +# scripts/release.sh sign|notarize|dmg # individual steps | |
| 15 | + | |
| 16 | +set -euo pipefail | |
| 17 | +cd "$(dirname "$0")/.." | |
| 18 | + | |
| 19 | +IDENTITY="Developer ID Application: Simon-Pierre Boucher (3YM54G49SN)" | |
| 20 | +KEYCHAIN_PROFILE="MacLustr-Notarize" | |
| 21 | +APP_DIR="dist/OS Vault.app" | |
| 22 | +ZIP_NAME="dist/OSVault.zip" | |
| 23 | +DMG_NAME="dist/OSVault.dmg" | |
| 24 | +ENTITLEMENTS="Support/entitlements.plist" | |
| 25 | + | |
| 26 | +build() { | |
| 27 | + echo "=== Release build + bundle ===" | |
| 28 | + make bundle-release | |
| 29 | +} | |
| 30 | + | |
| 31 | +sign() { | |
| 32 | + [ -d "$APP_DIR" ] || { echo "ERROR: $APP_DIR missing — run 'make bundle-release' first" >&2; exit 1; } | |
| 33 | + echo "=== Signing (Developer ID, hardened runtime, sandboxed) ===" | |
| 34 | + codesign --force --options runtime --timestamp \ | |
| 35 | + --entitlements "$ENTITLEMENTS" \ | |
| 36 | + --sign "$IDENTITY" "$APP_DIR" | |
| 37 | + codesign --verify --deep --strict --verbose=2 "$APP_DIR" | |
| 38 | + echo "Signature valid." | |
| 39 | +} | |
| 40 | + | |
| 41 | +notarize() { | |
| 42 | + echo "=== Notarizing app (profile: $KEYCHAIN_PROFILE) ===" | |
| 43 | + rm -f "$ZIP_NAME" | |
| 44 | + ditto -c -k --keepParent "$APP_DIR" "$ZIP_NAME" | |
| 45 | + xcrun notarytool submit "$ZIP_NAME" --keychain-profile "$KEYCHAIN_PROFILE" --wait | |
| 46 | + xcrun stapler staple "$APP_DIR" | |
| 47 | + xcrun stapler validate "$APP_DIR" | |
| 48 | + spctl -a -vv "$APP_DIR" | |
| 49 | + echo "App notarized and stapled." | |
| 50 | +} | |
| 51 | + | |
| 52 | +dmg() { | |
| 53 | + echo "=== Creating signed + notarized DMG (custom volume icon) ===" | |
| 54 | + rm -f "$DMG_NAME" | |
| 55 | + DMG_TEMP="dist/dmg_temp" | |
| 56 | + DMG_RW="dist/OSVault-rw.dmg" | |
| 57 | + rm -rf "$DMG_TEMP" "$DMG_RW" | |
| 58 | + mkdir -p "$DMG_TEMP" | |
| 59 | + cp -R "$APP_DIR" "$DMG_TEMP/" | |
| 60 | + ln -s /Applications "$DMG_TEMP/Applications" | |
| 61 | + cp assets/icon/AppIcon.icns "$DMG_TEMP/.VolumeIcon.icns" | |
| 62 | + | |
| 63 | + # Read-write image first so the volume's custom-icon flag can be set, | |
| 64 | + # then compress to the final UDZO. | |
| 65 | + hdiutil create -volname "OS Vault" -srcfolder "$DMG_TEMP" -ov -format UDRW "$DMG_RW" | |
| 66 | + MOUNT_DIR=$(hdiutil attach "$DMG_RW" -nobrowse | awk -F'\t' '/\/Volumes\//{print $NF; exit}') | |
| 67 | + SetFile -a C "$MOUNT_DIR" | |
| 68 | + hdiutil detach "$MOUNT_DIR" -quiet | |
| 69 | + hdiutil convert "$DMG_RW" -format UDZO -o "$DMG_NAME" | |
| 70 | + rm -rf "$DMG_TEMP" "$DMG_RW" | |
| 71 | + | |
| 72 | + codesign --force --sign "$IDENTITY" --timestamp "$DMG_NAME" | |
| 73 | + xcrun notarytool submit "$DMG_NAME" --keychain-profile "$KEYCHAIN_PROFILE" --wait | |
| 74 | + xcrun stapler staple "$DMG_NAME" | |
| 75 | + echo "DMG ready: $DMG_NAME" | |
| 76 | +} | |
| 77 | + | |
| 78 | +case "${1:-dist}" in | |
| 79 | + sign) sign ;; | |
| 80 | + notarize) notarize ;; | |
| 81 | + dmg) dmg ;; | |
| 82 | + dist) build; sign; notarize; dmg ;; | |
| 83 | + *) echo "Usage: $0 {sign|notarize|dmg|dist}" >&2; exit 64 ;; | |
| 84 | +esac | |
added
scripts/vendor-walletcore.sh
+129 −0
@@ -0,0 +1,129 @@ | ||
| 1 | +#!/bin/bash | |
| 2 | +# | |
| 3 | +# vendor-walletcore.sh | |
| 4 | +# OS Vault | |
| 5 | +# | |
| 6 | +# Author: Simon-Pierre Boucher | |
| 7 | +# Mail: contact@spboucher.ai | |
| 8 | +# | |
| 9 | +# Vendors Trust wallet-core as a local SwiftPM package with native macOS | |
| 10 | +# support — the signing engine for the non-EVM expansion (Tron, TON, XRPL, | |
| 11 | +# Solana fallback…). Upstream's SPM package is iOS-only, but the official | |
| 12 | +# CocoaPods tarball ships a macos-arm64_x86_64 slice; this script repackages | |
| 13 | +# it, fully automated (proven working on this machine — see | |
| 14 | +# docs/RESEARCH-MULTICHAIN.md §wallet-core). | |
| 15 | +# | |
| 16 | +# Usage: scripts/vendor-walletcore.sh [version] (default 4.7.2) | |
| 17 | + | |
| 18 | +set -euo pipefail | |
| 19 | +cd "$(dirname "$0")/.." | |
| 20 | + | |
| 21 | +VERSION="${1:-4.7.2}" | |
| 22 | +URL="https://github.com/trustwallet/wallet-core/releases/download/${VERSION}/TrustWalletCore-${VERSION}.tar.xz" | |
| 23 | +DEST="vendor/WalletCoreSPM" | |
| 24 | +WORK="$(mktemp -d)" | |
| 25 | +trap 'rm -rf "$WORK"' EXIT | |
| 26 | + | |
| 27 | +echo "=== Downloading official wallet-core ${VERSION} tarball ===" | |
| 28 | +curl -fL --retry 3 -o "$WORK/twc.tar.xz" "$URL" | |
| 29 | +tar -xJf "$WORK/twc.tar.xz" -C "$WORK" | |
| 30 | +# The tarball extracts flat: include/ Sources/ WalletCoreCommon.xcframework | |
| 31 | +SRC="$WORK" | |
| 32 | +[ -d "$SRC/include/TrustWalletCore" ] && [ -d "$SRC/Sources" ] && [ -d "$SRC/WalletCoreCommon.xcframework" ] || | |
| 33 | + { echo "ERROR: tarball layout unexpected" >&2; exit 1; } | |
| 34 | + | |
| 35 | +echo "=== Assembling local SwiftPM package in $DEST ===" | |
| 36 | +rm -rf "$DEST" | |
| 37 | +mkdir -p "$DEST/Sources/WalletCoreC/include" "$DEST/Sources/WalletCore" | |
| 38 | + | |
| 39 | +# C target: public headers + the Security.framework RNG shim (SECURITY-CRITICAL: | |
| 40 | +# trezor-crypto takes entropy from these consumer-provided symbols). | |
| 41 | +cp -R "$SRC/include/TrustWalletCore" "$DEST/Sources/WalletCoreC/include/" | |
| 42 | +find "$SRC" -name 'SecRandom.m' -exec cp {} "$DEST/Sources/WalletCoreC/" \; | |
| 43 | +[ -f "$DEST/Sources/WalletCoreC/SecRandom.m" ] || { echo "ERROR: SecRandom.m missing" >&2; exit 1; } | |
| 44 | + | |
| 45 | +# Swift wrappers: rename the protobuf module, inject imports SPM needs. | |
| 46 | +cp -R "$SRC/Sources/." "$DEST/Sources/WalletCore/" | |
| 47 | +# Swift target must be Swift-only (SecRandom.m lives in WalletCoreC). | |
| 48 | +find "$DEST/Sources/WalletCore" \( -name '*.m' -o -name '*.h' \) -delete | |
| 49 | +# Global rename: the generated code also uses the module as a type qualifier. | |
| 50 | +find "$DEST/Sources/WalletCore" -name '*.swift' -exec sed -i '' \ | |
| 51 | + -e 's/WalletCoreSwiftProtobuf/SwiftProtobuf/g' {} \; | |
| 52 | +find "$DEST/Sources/WalletCore" -name '*.swift' -exec sed -i '' \ | |
| 53 | + -e '1s/^/import WalletCoreC\nimport Foundation\n/' {} \; | |
| 54 | + | |
| 55 | +# Native binary (contains the macos-arm64_x86_64 slice). | |
| 56 | +cp -R "$SRC/WalletCoreCommon.xcframework" "$DEST/" | |
| 57 | +plutil -p "$DEST/WalletCoreCommon.xcframework/Info.plist" | grep -q macos || | |
| 58 | + { echo "ERROR: no macOS slice in xcframework" >&2; exit 1; } | |
| 59 | + | |
| 60 | +# De-duplicate the Rust runtime: both wallet-core and bdkFFI (Bitcoin Dev Kit) | |
| 61 | +# statically embed Rust's std, and the linker rejects the duplicate global | |
| 62 | +# `_rust_eh_personality`. Demote wallet-core's copy to private in the single | |
| 63 | +# archive member that defines it (surgical — merging the whole archive breaks | |
| 64 | +# unused-member semantics). | |
| 65 | +echo "=== Demoting duplicate _rust_eh_personality in the macOS slice ===" | |
| 66 | +BIN="$DEST/WalletCoreCommon.xcframework/macos-arm64_x86_64/WalletCoreCommon.framework/Versions/A/WalletCoreCommon" | |
| 67 | +FIX="$WORK/rustfix" | |
| 68 | +mkdir -p "$FIX" | |
| 69 | +for arch in arm64 x86_64; do | |
| 70 | + mkdir -p "$FIX/$arch" | |
| 71 | + ( cd "$FIX/$arch" | |
| 72 | + lipo "$BIN" -thin "$arch" -output slice.a | |
| 73 | + MEMBER=$(nm -gU -A slice.a 2>/dev/null | grep " T _rust_eh_personality" | head -1 | cut -d: -f2) | |
| 74 | + [ -n "$MEMBER" ] || { echo "no duplicate in $arch (upstream fixed?) — skipping"; exit 0; } | |
| 75 | + ar -x slice.a "$MEMBER" | |
| 76 | + ld -r -arch "$arch" -platform_version macos 13.0 15.5 "$MEMBER" -o patched.o \ | |
| 77 | + -unexported_symbol _rust_eh_personality 2>/dev/null | |
| 78 | + mv patched.o "$MEMBER" | |
| 79 | + ar -r -s slice.a "$MEMBER" 2>/dev/null ) | |
| 80 | +done | |
| 81 | +lipo -create "$FIX/arm64/slice.a" "$FIX/x86_64/slice.a" -output "$BIN" | |
| 82 | + | |
| 83 | +cat > "$DEST/Package.swift" <<'EOF' | |
| 84 | +// swift-tools-version:5.10 | |
| 85 | +// Auto-generated by scripts/vendor-walletcore.sh — do not edit by hand. | |
| 86 | +// The prebuilt static framework is exposed as a local binaryTarget (no | |
| 87 | +// unsafeFlags — those would make the package unusable as a dependency). | |
| 88 | +import PackageDescription | |
| 89 | + | |
| 90 | +let package = Package( | |
| 91 | + name: "WalletCoreSPM", | |
| 92 | + platforms: [.macOS(.v13)], | |
| 93 | + products: [ | |
| 94 | + .library(name: "WalletCore", targets: ["WalletCore"]) | |
| 95 | + ], | |
| 96 | + dependencies: [ | |
| 97 | + .package(url: "https://github.com/apple/swift-protobuf.git", from: "1.29.0") | |
| 98 | + ], | |
| 99 | + targets: [ | |
| 100 | + .binaryTarget( | |
| 101 | + name: "WalletCoreBinary", | |
| 102 | + path: "WalletCoreCommon.xcframework" | |
| 103 | + ), | |
| 104 | + .target( | |
| 105 | + name: "WalletCoreC", | |
| 106 | + dependencies: ["WalletCoreBinary"], | |
| 107 | + path: "Sources/WalletCoreC", | |
| 108 | + publicHeadersPath: "include" | |
| 109 | + ), | |
| 110 | + .target( | |
| 111 | + name: "WalletCore", | |
| 112 | + dependencies: [ | |
| 113 | + "WalletCoreC", | |
| 114 | + .product(name: "SwiftProtobuf", package: "swift-protobuf") | |
| 115 | + ], | |
| 116 | + path: "Sources/WalletCore", | |
| 117 | + linkerSettings: [ | |
| 118 | + .linkedLibrary("c++"), | |
| 119 | + .linkedFramework("Security") | |
| 120 | + ] | |
| 121 | + ) | |
| 122 | + ] | |
| 123 | +) | |
| 124 | +EOF | |
| 125 | + | |
| 126 | +echo "=== Done ===" | |
| 127 | +echo "Vendored wallet-core ${VERSION} → $DEST" | |
| 128 | +echo "Add to Package.swift deps: .package(path: \"vendor/WalletCoreSPM\") and" | |
| 129 | +echo "product .product(name: \"WalletCore\", package: \"WalletCoreSPM\")." | |
| \ No newline at end of file | ||
added
vendor/WalletCoreSPM/Package.swift
+40 −0
@@ -0,0 +1,40 @@ | ||
| 1 | +// swift-tools-version:5.10 | |
| 2 | +// Auto-generated by scripts/vendor-walletcore.sh — do not edit by hand. | |
| 3 | +// The prebuilt static framework is exposed as a local binaryTarget (no | |
| 4 | +// unsafeFlags — those would make the package unusable as a dependency). | |
| 5 | +import PackageDescription | |
| 6 | + | |
| 7 | +let package = Package( | |
| 8 | + name: "WalletCoreSPM", | |
| 9 | + platforms: [.macOS(.v13)], | |
| 10 | + products: [ | |
| 11 | + .library(name: "WalletCore", targets: ["WalletCore"]) | |
| 12 | + ], | |
| 13 | + dependencies: [ | |
| 14 | + .package(url: "https://github.com/apple/swift-protobuf.git", from: "1.29.0") | |
| 15 | + ], | |
| 16 | + targets: [ | |
| 17 | + .binaryTarget( | |
| 18 | + name: "WalletCoreBinary", | |
| 19 | + path: "WalletCoreCommon.xcframework" | |
| 20 | + ), | |
| 21 | + .target( | |
| 22 | + name: "WalletCoreC", | |
| 23 | + dependencies: ["WalletCoreBinary"], | |
| 24 | + path: "Sources/WalletCoreC", | |
| 25 | + publicHeadersPath: "include" | |
| 26 | + ), | |
| 27 | + .target( | |
| 28 | + name: "WalletCore", | |
| 29 | + dependencies: [ | |
| 30 | + "WalletCoreC", | |
| 31 | + .product(name: "SwiftProtobuf", package: "swift-protobuf") | |
| 32 | + ], | |
| 33 | + path: "Sources/WalletCore", | |
| 34 | + linkerSettings: [ | |
| 35 | + .linkedLibrary("c++"), | |
| 36 | + .linkedFramework("Security") | |
| 37 | + ] | |
| 38 | + ) | |
| 39 | + ] | |
| 40 | +) | |
added
vendor/WalletCoreSPM/Sources/WalletCore/AnySigner.swift
+96 −0
@@ -0,0 +1,96 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// Copyright © 2017-2018 Trust. | |
| 4 | +// | |
| 5 | +// This file is part of Trust. The full Trust copyright notice, including | |
| 6 | +// terms governing use, modification, and redistribution, is contained in the | |
| 7 | +// file LICENSE at the root of the source code distribution tree. | |
| 8 | + | |
| 9 | +import Foundation | |
| 10 | +import SwiftProtobuf | |
| 11 | + | |
| 12 | +public typealias SigningInput = Message | |
| 13 | +public typealias SigningOutput = Message | |
| 14 | + | |
| 15 | +/// Represents a signer to sign transactions for any blockchain. | |
| 16 | +public final class AnySigner { | |
| 17 | + | |
| 18 | + /// Signs a transaction by SigningInput message and coin type | |
| 19 | + /// | |
| 20 | + /// - Parameters: | |
| 21 | + /// - input: The generic SigningInput SwiftProtobuf message | |
| 22 | + /// - coin: CoinType | |
| 23 | + /// - Returns: The generic SigningOutput SwiftProtobuf message | |
| 24 | + public static func sign<SigningOutput: Message>(input: SigningInput, coin: CoinType) -> SigningOutput { | |
| 25 | + do { | |
| 26 | + let outputData = nativeSign(data: try input.serializedData(), coin: coin) | |
| 27 | + return try SigningOutput(serializedBytes: outputData) | |
| 28 | + } catch let error { | |
| 29 | + fatalError(error.localizedDescription) | |
| 30 | + } | |
| 31 | + } | |
| 32 | + | |
| 33 | + /// Signs a transaction by serialized data of a SigningInput and coin type | |
| 34 | + /// | |
| 35 | + /// - Parameters: | |
| 36 | + /// - data: The serialized data of a SigningInput | |
| 37 | + /// - coin: CoinType | |
| 38 | + /// - Returns: The serialized data of a SigningOutput | |
| 39 | + public static func nativeSign(data: Data, coin: CoinType) -> Data { | |
| 40 | + let inputData = TWDataCreateWithNSData(data) | |
| 41 | + defer { | |
| 42 | + TWDataDelete(inputData) | |
| 43 | + } | |
| 44 | + return TWDataNSData(TWAnySignerSign(inputData, TWCoinType(rawValue: coin.rawValue))) | |
| 45 | + } | |
| 46 | + | |
| 47 | + /// Check if AnySigner supports signing JSON representation of SigningInput for a given coin. | |
| 48 | + public static func supportsJSON(coin: CoinType) -> Bool { | |
| 49 | + return TWAnySignerSupportsJSON(TWCoinType(rawValue: coin.rawValue)) | |
| 50 | + } | |
| 51 | + | |
| 52 | + /// Signs a transaction specified by the JSON representation of a SigningInput, coin type and a private key | |
| 53 | + /// | |
| 54 | + /// - Parameters: | |
| 55 | + /// - json: JSON representation of a SigningInput | |
| 56 | + /// - key: The private key data | |
| 57 | + /// - coin: CoinType | |
| 58 | + /// - Returns: The JSON representation of a SigningOutput. | |
| 59 | + public static func signJSON(_ json: String, key: Data, coin: CoinType) -> String { | |
| 60 | + let jsonString = TWStringCreateWithNSString(json) | |
| 61 | + let keyData = TWDataCreateWithNSData(key) | |
| 62 | + defer { | |
| 63 | + TWDataDelete(keyData) | |
| 64 | + } | |
| 65 | + return TWStringNSString(TWAnySignerSignJSON(jsonString, keyData, TWCoinType(rawValue: coin.rawValue))) | |
| 66 | + } | |
| 67 | + | |
| 68 | + /// Plans a transaction (for UTXO chains only). | |
| 69 | + /// | |
| 70 | + /// - Parameters: | |
| 71 | + /// - input: The generic SigningInput SwiftProtobuf message | |
| 72 | + /// - coin: CoinType | |
| 73 | + /// - Returns: TransactionPlan SwiftProtobuf message | |
| 74 | + public static func plan<TransactionPlan: Message>(input: SigningInput, coin: CoinType) -> TransactionPlan { | |
| 75 | + do { | |
| 76 | + let outputData = nativePlan(data: try input.serializedData(), coin: coin) | |
| 77 | + return try TransactionPlan(serializedBytes: outputData) | |
| 78 | + } catch let error { | |
| 79 | + fatalError(error.localizedDescription) | |
| 80 | + } | |
| 81 | + } | |
| 82 | + | |
| 83 | + /// Plans a transaction (for UTXO chains only). | |
| 84 | + /// | |
| 85 | + /// - Parameters: | |
| 86 | + /// - input: The serialized data of a SigningInput | |
| 87 | + /// - coin: CoinType | |
| 88 | + /// - Returns: The serialized data of a TransactionPlan | |
| 89 | + public static func nativePlan(data: Data, coin: CoinType) -> Data { | |
| 90 | + let inputData = TWDataCreateWithNSData(data) | |
| 91 | + defer { | |
| 92 | + TWDataDelete(inputData) | |
| 93 | + } | |
| 94 | + return TWDataNSData(TWAnySignerPlan(inputData, TWCoinType(rawValue: coin.rawValue))) | |
| 95 | + } | |
| 96 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/Account+Codable.swift
+92 −0
@@ -0,0 +1,92 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +import Foundation | |
| 8 | + | |
| 9 | +extension Account: Equatable { | |
| 10 | + public static func == (lhs: Account, rhs: Account) -> Bool { | |
| 11 | + return lhs.coin == rhs.coin && | |
| 12 | + lhs.address == rhs.address && | |
| 13 | + lhs.derivation == rhs.derivation && | |
| 14 | + lhs.derivationPath == rhs.derivationPath && | |
| 15 | + lhs.publicKey == rhs.publicKey && | |
| 16 | + lhs.extendedPublicKey == rhs.extendedPublicKey | |
| 17 | + } | |
| 18 | +} | |
| 19 | + | |
| 20 | +extension Account: Hashable { | |
| 21 | + public func hash(into hasher: inout Hasher) { | |
| 22 | + hasher.combine(coin) | |
| 23 | + hasher.combine(address) | |
| 24 | + hasher.combine(derivation) | |
| 25 | + hasher.combine(derivationPath) | |
| 26 | + hasher.combine(publicKey) | |
| 27 | + hasher.combine(extendedPublicKey) | |
| 28 | + } | |
| 29 | +} | |
| 30 | + | |
| 31 | +extension Account: Codable { | |
| 32 | + private enum CodingKeys: String, CodingKey { | |
| 33 | + case coin | |
| 34 | + case address | |
| 35 | + case derivation | |
| 36 | + case derivationPath | |
| 37 | + case publicKey | |
| 38 | + case extendedPublicKey | |
| 39 | + } | |
| 40 | + | |
| 41 | + public func encode(to encoder: Encoder) throws { | |
| 42 | + var container = encoder.container(keyedBy: CodingKeys.self) | |
| 43 | + try container.encode(coin.rawValue, forKey: .coin) | |
| 44 | + try container.encode(address, forKey: .address) | |
| 45 | + try container.encode(derivation.rawValue, forKey: .derivation) | |
| 46 | + try container.encode(derivationPath, forKey: .derivationPath) | |
| 47 | + try container.encode(publicKey, forKey: .publicKey) | |
| 48 | + try container.encode(extendedPublicKey, forKey: .extendedPublicKey) | |
| 49 | + } | |
| 50 | + | |
| 51 | + public convenience init(from decoder: Decoder) throws { | |
| 52 | + let container = try decoder.container(keyedBy: CodingKeys.self) | |
| 53 | + let rawCoin = try container.decode(UInt32.self, forKey: .coin) | |
| 54 | + let address = try container.decode(String.self, forKey: .address) | |
| 55 | + let rawDerivation = try container.decode(UInt32.self, forKey: .derivation) | |
| 56 | + let derivationPath = try container.decode(String.self, forKey: .derivationPath) | |
| 57 | + let publicKey = try container.decode(String.self, forKey: .publicKey) | |
| 58 | + let extendedPublicKey = try container.decode(String.self, forKey: .extendedPublicKey) | |
| 59 | + | |
| 60 | + guard let coin = CoinType(rawValue: rawCoin) else { | |
| 61 | + throw DecodingError.dataCorruptedError(forKey: .coin, in: container, | |
| 62 | + debugDescription: "Unknown coin type: \(rawCoin)") | |
| 63 | + } | |
| 64 | + guard let derivation = Derivation(rawValue: rawDerivation) else { | |
| 65 | + throw DecodingError.dataCorruptedError(forKey: .derivation, in: container, | |
| 66 | + debugDescription: "Unknown derivation: \(rawDerivation)") | |
| 67 | + } | |
| 68 | + // Call TWAccountCreate directly rather than using the Account failable init: | |
| 69 | + // if we created an intermediate Account and copied its rawValue, that wrapper's | |
| 70 | + // deinit would call TWAccountDelete before self uses the pointer (use-after-free). | |
| 71 | + let addressString = TWStringCreateWithNSString(address) | |
| 72 | + defer { TWStringDelete(addressString) } | |
| 73 | + let derivationPathString = TWStringCreateWithNSString(derivationPath) | |
| 74 | + defer { TWStringDelete(derivationPathString) } | |
| 75 | + let publicKeyString = TWStringCreateWithNSString(publicKey) | |
| 76 | + defer { TWStringDelete(publicKeyString) } | |
| 77 | + let extendedPublicKeyString = TWStringCreateWithNSString(extendedPublicKey) | |
| 78 | + defer { TWStringDelete(extendedPublicKeyString) } | |
| 79 | + guard let rawValue = TWAccountCreate( | |
| 80 | + addressString, | |
| 81 | + TWCoinType(rawValue: coin.rawValue), | |
| 82 | + TWDerivation(rawValue: derivation.rawValue), | |
| 83 | + derivationPathString, | |
| 84 | + publicKeyString, | |
| 85 | + extendedPublicKeyString | |
| 86 | + ) else { | |
| 87 | + throw DecodingError.dataCorruptedError(forKey: .derivationPath, in: container, | |
| 88 | + debugDescription: "Invalid derivation path: \(derivationPath)") | |
| 89 | + } | |
| 90 | + self.init(rawValue: rawValue) | |
| 91 | + } | |
| 92 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/AddressProtocol.swift
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +import Foundation | |
| 8 | + | |
| 9 | +/// Generic Address protocol for AnyAddress / SegwitAddress / SolanaAddress | |
| 10 | +public protocol Address: CustomStringConvertible {} | |
| 11 | + | |
| 12 | +extension AnyAddress: Equatable {} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/BitcoinAddress+Extension.swift
+25 −0
@@ -0,0 +1,25 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +import Foundation | |
| 8 | + | |
| 9 | +extension BitcoinAddress: Equatable { | |
| 10 | + public var base58String: String { | |
| 11 | + return description | |
| 12 | + } | |
| 13 | + | |
| 14 | + public func hash(into hasher: inout Hasher) { | |
| 15 | + hasher.combine(description) | |
| 16 | + } | |
| 17 | + | |
| 18 | + /// Creates a legacy Bitcoin address for segwit redeem script. | |
| 19 | + public static func compatibleAddress(publicKey: PublicKey, prefix: UInt8) -> BitcoinAddress { | |
| 20 | + let witnessVersion = Data([0x00, 0x14]) | |
| 21 | + let redeemScript = Hash.sha256RIPEMD(data: witnessVersion + publicKey.bitcoinKeyHash) | |
| 22 | + let address = Base58.encode(data: [prefix] + redeemScript) | |
| 23 | + return BitcoinAddress(string: address)! | |
| 24 | + } | |
| 25 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/CoinType+Address.swift
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +import Foundation | |
| 8 | + | |
| 9 | +public extension CoinType { | |
| 10 | + /// Converts a string to an address for this coin type. | |
| 11 | + func address(string: String) -> AnyAddress? { | |
| 12 | + return AnyAddress(string: string, coin: self) | |
| 13 | + } | |
| 14 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/Data+Hex.swift
+84 −0
@@ -0,0 +1,84 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +import Foundation | |
| 8 | + | |
| 9 | +extension Data { | |
| 10 | + /// Initializes `Data` with a hex string representation. | |
| 11 | + public init?(hexString: String) { | |
| 12 | + let string: String | |
| 13 | + if hexString.hasPrefix("0x") { | |
| 14 | + string = String(hexString.dropFirst(2)) | |
| 15 | + } else { | |
| 16 | + string = hexString | |
| 17 | + } | |
| 18 | + | |
| 19 | + // Check odd length hex string | |
| 20 | + if string.count % 2 != 0 { | |
| 21 | + return nil | |
| 22 | + } | |
| 23 | + | |
| 24 | + // Check odd characters | |
| 25 | + if string.contains(where: { !$0.isHexDigit }) { | |
| 26 | + return nil | |
| 27 | + } | |
| 28 | + | |
| 29 | + // Convert the string to bytes for better performance | |
| 30 | + guard let stringData = string.data(using: .ascii, allowLossyConversion: true) else { | |
| 31 | + return nil | |
| 32 | + } | |
| 33 | + | |
| 34 | + self.init(capacity: string.count / 2) | |
| 35 | + let stringBytes = Array(stringData) | |
| 36 | + for i in stride(from: 0, to: stringBytes.count, by: 2) { | |
| 37 | + guard let high = Data.value(of: stringBytes[i]) else { | |
| 38 | + return nil | |
| 39 | + } | |
| 40 | + if i < stringBytes.count - 1, let low = Data.value(of: stringBytes[i + 1]) { | |
| 41 | + append((high << 4) | low) | |
| 42 | + } else { | |
| 43 | + append(high) | |
| 44 | + } | |
| 45 | + } | |
| 46 | + } | |
| 47 | + | |
| 48 | + /// Converts an ASCII byte to a hex value. | |
| 49 | + private static func value(of nibble: UInt8) -> UInt8? { | |
| 50 | + guard let letter = String(bytes: [nibble], encoding: .ascii) else { return nil } | |
| 51 | + return UInt8(letter, radix: 16) | |
| 52 | + } | |
| 53 | + | |
| 54 | + /// Reverses and parses hex string as `Data` | |
| 55 | + public static func reverse(hexString: String) -> Data { | |
| 56 | + guard let data = Data(hexString: hexString) else { return Data() } | |
| 57 | + return Data(data.reversed()) | |
| 58 | + } | |
| 59 | + | |
| 60 | + /// Returns the hex string representation of the data. | |
| 61 | + public var hexString: String { | |
| 62 | + return map({ String(format: "%02x", $0) }).joined() | |
| 63 | + } | |
| 64 | +} | |
| 65 | + | |
| 66 | +public extension KeyedDecodingContainerProtocol { | |
| 67 | + func decodeHexString(forKey key: Self.Key) throws -> Data { | |
| 68 | + let hexString = try decode(String.self, forKey: key) | |
| 69 | + guard let data = Data(hexString: hexString) else { | |
| 70 | + throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Expected hexadecimal string") | |
| 71 | + } | |
| 72 | + return data | |
| 73 | + } | |
| 74 | + | |
| 75 | + func decodeHexStringIfPresent(forKey key: Self.Key) throws -> Data? { | |
| 76 | + guard let hexString = try decodeIfPresent(String.self, forKey: key) else { | |
| 77 | + return nil | |
| 78 | + } | |
| 79 | + guard let data = Data(hexString: hexString) else { | |
| 80 | + throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Expected hexadecimal string") | |
| 81 | + } | |
| 82 | + return data | |
| 83 | + } | |
| 84 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/DerivationPath+Extension.swift
+119 −0
@@ -0,0 +1,119 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +import Foundation | |
| 8 | + | |
| 9 | +extension DerivationPath: Equatable, Hashable, CustomStringConvertible { | |
| 10 | + | |
| 11 | + public typealias Index = DerivationPathIndex | |
| 12 | + | |
| 13 | + public static func == (lhs: DerivationPath, rhs: DerivationPath) -> Bool { | |
| 14 | + return lhs.description == rhs.description | |
| 15 | + } | |
| 16 | + | |
| 17 | + public var coinType: UInt32 { | |
| 18 | + coin | |
| 19 | + } | |
| 20 | + | |
| 21 | + public var indices: [Index] { | |
| 22 | + var result = [Index]() | |
| 23 | + for i in 0..<indicesCount() { | |
| 24 | + guard let index = indexAt(index: i) else { | |
| 25 | + continue | |
| 26 | + } | |
| 27 | + result.append(index) | |
| 28 | + } | |
| 29 | + return result | |
| 30 | + } | |
| 31 | + | |
| 32 | + public convenience init(purpose: Purpose, coin: UInt32) { | |
| 33 | + self.init(purpose: purpose, coin: coin, account: 0, change: 0, address: 0) | |
| 34 | + } | |
| 35 | + | |
| 36 | + public convenience init?(_ string: String) { | |
| 37 | + self.init(string: string) | |
| 38 | + } | |
| 39 | + | |
| 40 | + public subscript(index: Int) -> DerivationPathIndex? { | |
| 41 | + return self.indexAt(index: UInt32(index)) | |
| 42 | + } | |
| 43 | + | |
| 44 | + public func hash(into hasher: inout Hasher) { | |
| 45 | + let count = indicesCount() | |
| 46 | + for i in 0..<count { | |
| 47 | + hasher.combine(self[Int(i)]) | |
| 48 | + } | |
| 49 | + } | |
| 50 | +} | |
| 51 | + | |
| 52 | +extension DerivationPath: Codable { | |
| 53 | + private enum CodingKeys: String, CodingKey { | |
| 54 | + case purpose | |
| 55 | + case coin | |
| 56 | + case account | |
| 57 | + case change | |
| 58 | + case address | |
| 59 | + } | |
| 60 | + | |
| 61 | + public func encode(to encoder: Encoder) throws { | |
| 62 | + var container = encoder.container(keyedBy: CodingKeys.self) | |
| 63 | + try container.encode(purpose.rawValue, forKey: .purpose) | |
| 64 | + try container.encode(coin, forKey: .coin) | |
| 65 | + try container.encode(account, forKey: .account) | |
| 66 | + try container.encode(change, forKey: .change) | |
| 67 | + try container.encode(address, forKey: .address) | |
| 68 | + } | |
| 69 | + | |
| 70 | + public convenience init(from decoder: Decoder) throws { | |
| 71 | + let container = try decoder.container(keyedBy: CodingKeys.self) | |
| 72 | + let purpose = try container.decode(UInt32.self, forKey: .purpose) | |
| 73 | + guard | |
| 74 | + let purposeEnum = Purpose(rawValue: purpose) | |
| 75 | + else { | |
| 76 | + throw DecodingError.dataCorruptedError(forKey: CodingKeys.purpose, in: container, debugDescription: "purpose value is not valid") | |
| 77 | + } | |
| 78 | + let coin = try container.decode(UInt32.self, forKey: .coin) | |
| 79 | + let account = try container.decode(UInt32.self, forKey: .account) | |
| 80 | + let change = try container.decode(UInt32.self, forKey: .change) | |
| 81 | + let address = try container.decode(UInt32.self, forKey: .address) | |
| 82 | + self.init(purpose: purposeEnum, coin: coin, account: account, change: change, address: address) | |
| 83 | + } | |
| 84 | +} | |
| 85 | + | |
| 86 | +extension DerivationPathIndex: Equatable, Hashable, CustomStringConvertible { | |
| 87 | + public static func == (lhs: DerivationPathIndex, rhs: DerivationPathIndex) -> Bool { | |
| 88 | + return lhs.value == rhs.value && lhs.hardened == rhs.hardened | |
| 89 | + } | |
| 90 | + | |
| 91 | + public convenience init(_ value: UInt32, hardened: Bool) { | |
| 92 | + self.init(value: value, hardened: hardened) | |
| 93 | + } | |
| 94 | + | |
| 95 | + public func hash(into hasher: inout Hasher) { | |
| 96 | + hasher.combine(value) | |
| 97 | + hasher.combine(hardened) | |
| 98 | + } | |
| 99 | +} | |
| 100 | + | |
| 101 | +extension DerivationPathIndex: Codable { | |
| 102 | + private enum CodingKeys: String, CodingKey { | |
| 103 | + case value | |
| 104 | + case hardened | |
| 105 | + } | |
| 106 | + | |
| 107 | + public func encode(to encoder: Encoder) throws { | |
| 108 | + var container = encoder.container(keyedBy: CodingKeys.self) | |
| 109 | + try container.encode(value, forKey: .value) | |
| 110 | + try container.encode(hardened, forKey: .hardened) | |
| 111 | + } | |
| 112 | + | |
| 113 | + public convenience init(from decoder: Decoder) throws { | |
| 114 | + let container = try decoder.container(keyedBy: CodingKeys.self) | |
| 115 | + let value = try container.decode(UInt32.self, forKey: .value) | |
| 116 | + let hardened = try container.decode(Bool.self, forKey: .hardened) | |
| 117 | + self.init(value: value, hardened: hardened) | |
| 118 | + } | |
| 119 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/Mnemonic+Extension.swift
+26 −0
@@ -0,0 +1,26 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +import Foundation | |
| 8 | + | |
| 9 | +public extension Mnemonic { | |
| 10 | + typealias ValidationResult = (word: String, index: Int) | |
| 11 | + | |
| 12 | + /// Returns mnemonic validation result, an array of wrong word and index tuple | |
| 13 | + static func validate(mnemonic: [String]) -> [ValidationResult] { | |
| 14 | + mnemonic.enumerated().compactMap { (index, word) -> ValidationResult? in | |
| 15 | + if isValidWord(word: word) { | |
| 16 | + return nil | |
| 17 | + } | |
| 18 | + return (word, index) | |
| 19 | + } | |
| 20 | + } | |
| 21 | + | |
| 22 | + /// Returns matched suggestion in a native array | |
| 23 | + static func search(prefix: String) -> [String] { | |
| 24 | + return suggest(prefix: prefix).split(separator: " ").map { String($0) } | |
| 25 | + } | |
| 26 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Extensions/PublicKey+Bitcoin.swift
+12 −0
@@ -0,0 +1,12 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public extension PublicKey { | |
| 8 | + /// Returns the ripemd160 hash of the sha2 hash of the compressed public key data. | |
| 9 | + var bitcoinKeyHash: Data { | |
| 10 | + return Hash.sha256RIPEMD(data: compressed.data) | |
| 11 | + } | |
| 12 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/AES.swift
+122 −0
@@ -0,0 +1,122 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// AES encryption/decryption methods. | |
| 13 | +public struct AES { | |
| 14 | + | |
| 15 | + /// Encrypts a block of Data using AES in Cipher Block Chaining (CBC) mode. | |
| 16 | + /// | |
| 17 | + /// - Parameter key: encryption key Data, must be 16, 24, or 32 bytes long. | |
| 18 | + /// - Parameter data: Data to encrypt. | |
| 19 | + /// - Parameter iv: initialization vector. | |
| 20 | + /// - Parameter mode: padding mode. | |
| 21 | + /// - Returns: encrypted Data. | |
| 22 | + public static func encryptCBC(key: Data, data: Data, iv: Data, mode: AESPaddingMode) -> Data? { | |
| 23 | + let keyData = TWDataCreateWithNSData(key) | |
| 24 | + defer { | |
| 25 | + TWDataDelete(keyData) | |
| 26 | + } | |
| 27 | + let dataData = TWDataCreateWithNSData(data) | |
| 28 | + defer { | |
| 29 | + TWDataDelete(dataData) | |
| 30 | + } | |
| 31 | + let ivData = TWDataCreateWithNSData(iv) | |
| 32 | + defer { | |
| 33 | + TWDataDelete(ivData) | |
| 34 | + } | |
| 35 | + guard let result = TWAESEncryptCBC(keyData, dataData, ivData, TWAESPaddingMode(rawValue: mode.rawValue)) else { | |
| 36 | + return nil | |
| 37 | + } | |
| 38 | + return TWDataNSData(result) | |
| 39 | + } | |
| 40 | + | |
| 41 | + /// Decrypts a block of data using AES in Cipher Block Chaining (CBC) mode. | |
| 42 | + /// | |
| 43 | + /// - Parameter key: decryption key Data, must be 16, 24, or 32 bytes long. | |
| 44 | + /// - Parameter data: Data to decrypt. | |
| 45 | + /// - Parameter iv: initialization vector Data. | |
| 46 | + /// - Parameter mode: padding mode. | |
| 47 | + /// - Returns: decrypted Data. | |
| 48 | + public static func decryptCBC(key: Data, data: Data, iv: Data, mode: AESPaddingMode) -> Data? { | |
| 49 | + let keyData = TWDataCreateWithNSData(key) | |
| 50 | + defer { | |
| 51 | + TWDataDelete(keyData) | |
| 52 | + } | |
| 53 | + let dataData = TWDataCreateWithNSData(data) | |
| 54 | + defer { | |
| 55 | + TWDataDelete(dataData) | |
| 56 | + } | |
| 57 | + let ivData = TWDataCreateWithNSData(iv) | |
| 58 | + defer { | |
| 59 | + TWDataDelete(ivData) | |
| 60 | + } | |
| 61 | + guard let result = TWAESDecryptCBC(keyData, dataData, ivData, TWAESPaddingMode(rawValue: mode.rawValue)) else { | |
| 62 | + return nil | |
| 63 | + } | |
| 64 | + return TWDataNSData(result) | |
| 65 | + } | |
| 66 | + | |
| 67 | + /// Encrypts a block of data using AES in Counter (CTR) mode. | |
| 68 | + /// | |
| 69 | + /// - Parameter key: encryption key Data, must be 16, 24, or 32 bytes long. | |
| 70 | + /// - Parameter data: Data to encrypt. | |
| 71 | + /// - Parameter iv: initialization vector Data. | |
| 72 | + /// - Returns: encrypted Data. | |
| 73 | + public static func encryptCTR(key: Data, data: Data, iv: Data) -> Data? { | |
| 74 | + let keyData = TWDataCreateWithNSData(key) | |
| 75 | + defer { | |
| 76 | + TWDataDelete(keyData) | |
| 77 | + } | |
| 78 | + let dataData = TWDataCreateWithNSData(data) | |
| 79 | + defer { | |
| 80 | + TWDataDelete(dataData) | |
| 81 | + } | |
| 82 | + let ivData = TWDataCreateWithNSData(iv) | |
| 83 | + defer { | |
| 84 | + TWDataDelete(ivData) | |
| 85 | + } | |
| 86 | + guard let result = TWAESEncryptCTR(keyData, dataData, ivData) else { | |
| 87 | + return nil | |
| 88 | + } | |
| 89 | + return TWDataNSData(result) | |
| 90 | + } | |
| 91 | + | |
| 92 | + /// Decrypts a block of data using AES in Counter (CTR) mode. | |
| 93 | + /// | |
| 94 | + /// - Parameter key: decryption key Data, must be 16, 24, or 32 bytes long. | |
| 95 | + /// - Parameter data: Data to decrypt. | |
| 96 | + /// - Parameter iv: initialization vector Data. | |
| 97 | + /// - Returns: decrypted Data. | |
| 98 | + public static func decryptCTR(key: Data, data: Data, iv: Data) -> Data? { | |
| 99 | + let keyData = TWDataCreateWithNSData(key) | |
| 100 | + defer { | |
| 101 | + TWDataDelete(keyData) | |
| 102 | + } | |
| 103 | + let dataData = TWDataCreateWithNSData(data) | |
| 104 | + defer { | |
| 105 | + TWDataDelete(dataData) | |
| 106 | + } | |
| 107 | + let ivData = TWDataCreateWithNSData(iv) | |
| 108 | + defer { | |
| 109 | + TWDataDelete(ivData) | |
| 110 | + } | |
| 111 | + guard let result = TWAESDecryptCTR(keyData, dataData, ivData) else { | |
| 112 | + return nil | |
| 113 | + } | |
| 114 | + return TWDataNSData(result) | |
| 115 | + } | |
| 116 | + | |
| 117 | + | |
| 118 | + init() { | |
| 119 | + } | |
| 120 | + | |
| 121 | + | |
| 122 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Account.swift
+90 −0
@@ -0,0 +1,90 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents an Account in C++ with address, coin type and public key info, an item within a keystore. | |
| 13 | +public final class Account { | |
| 14 | + | |
| 15 | + /// Returns the address of an account. | |
| 16 | + /// | |
| 17 | + /// - Parameter account: Account to get the address of. | |
| 18 | + public var address: String { | |
| 19 | + return TWStringNSString(TWAccountAddress(rawValue)) | |
| 20 | + } | |
| 21 | + | |
| 22 | + /// Return CoinType enum of an account. | |
| 23 | + /// | |
| 24 | + /// - Parameter account: Account to get the coin type of. | |
| 25 | + public var coin: CoinType { | |
| 26 | + return CoinType(rawValue: TWAccountCoin(rawValue).rawValue)! | |
| 27 | + } | |
| 28 | + | |
| 29 | + /// Returns the derivation enum of an account. | |
| 30 | + /// | |
| 31 | + /// - Parameter account: Account to get the derivation enum of. | |
| 32 | + public var derivation: Derivation { | |
| 33 | + return Derivation(rawValue: TWAccountDerivation(rawValue).rawValue)! | |
| 34 | + } | |
| 35 | + | |
| 36 | + /// Returns derivationPath of an account. | |
| 37 | + /// | |
| 38 | + /// - Parameter account: Account to get the derivation path of. | |
| 39 | + public var derivationPath: String { | |
| 40 | + return TWStringNSString(TWAccountDerivationPath(rawValue)) | |
| 41 | + } | |
| 42 | + | |
| 43 | + /// Returns hex encoded publicKey of an account. | |
| 44 | + /// | |
| 45 | + /// - Parameter account: Account to get the public key of. | |
| 46 | + public var publicKey: String { | |
| 47 | + return TWStringNSString(TWAccountPublicKey(rawValue)) | |
| 48 | + } | |
| 49 | + | |
| 50 | + /// Returns Base58 encoded extendedPublicKey of an account. | |
| 51 | + /// | |
| 52 | + /// - Parameter account: Account to get the extended public key of. | |
| 53 | + public var extendedPublicKey: String { | |
| 54 | + return TWStringNSString(TWAccountExtendedPublicKey(rawValue)) | |
| 55 | + } | |
| 56 | + | |
| 57 | + let rawValue: OpaquePointer | |
| 58 | + | |
| 59 | + init(rawValue: OpaquePointer) { | |
| 60 | + self.rawValue = rawValue | |
| 61 | + } | |
| 62 | + | |
| 63 | + public init?(address: String, coin: CoinType, derivation: Derivation, derivationPath: String, publicKey: String, extendedPublicKey: String) { | |
| 64 | + let addressString = TWStringCreateWithNSString(address) | |
| 65 | + defer { | |
| 66 | + TWStringDelete(addressString) | |
| 67 | + } | |
| 68 | + let derivationPathString = TWStringCreateWithNSString(derivationPath) | |
| 69 | + defer { | |
| 70 | + TWStringDelete(derivationPathString) | |
| 71 | + } | |
| 72 | + let publicKeyString = TWStringCreateWithNSString(publicKey) | |
| 73 | + defer { | |
| 74 | + TWStringDelete(publicKeyString) | |
| 75 | + } | |
| 76 | + let extendedPublicKeyString = TWStringCreateWithNSString(extendedPublicKey) | |
| 77 | + defer { | |
| 78 | + TWStringDelete(extendedPublicKeyString) | |
| 79 | + } | |
| 80 | + guard let rawValue = TWAccountCreate(addressString, TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue), derivationPathString, publicKeyString, extendedPublicKeyString) else { | |
| 81 | + return nil | |
| 82 | + } | |
| 83 | + self.rawValue = rawValue | |
| 84 | + } | |
| 85 | + | |
| 86 | + deinit { | |
| 87 | + TWAccountDelete(rawValue) | |
| 88 | + } | |
| 89 | + | |
| 90 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/AnyAddress.swift
+165 −0
@@ -0,0 +1,165 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents an address in C++ for almost any blockchain. | |
| 13 | +public final class AnyAddress: Address { | |
| 14 | + | |
| 15 | + /// Compares two addresses for equality. | |
| 16 | + /// | |
| 17 | + /// - Parameter lhs: The first address to compare. | |
| 18 | + /// - Parameter rhs: The second address to compare. | |
| 19 | + /// - Returns: bool indicating the addresses are equal. | |
| 20 | + public static func == (lhs: AnyAddress, rhs: AnyAddress) -> Bool { | |
| 21 | + return TWAnyAddressEqual(lhs.rawValue, rhs.rawValue) | |
| 22 | + } | |
| 23 | + | |
| 24 | + /// Determines if the string is a valid Any address. | |
| 25 | + /// | |
| 26 | + /// - Parameter string: address to validate. | |
| 27 | + /// - Parameter coin: coin type of the address. | |
| 28 | + /// - Returns: bool indicating if the address is valid. | |
| 29 | + public static func isValid(string: String, coin: CoinType) -> Bool { | |
| 30 | + let stringString = TWStringCreateWithNSString(string) | |
| 31 | + defer { | |
| 32 | + TWStringDelete(stringString) | |
| 33 | + } | |
| 34 | + return TWAnyAddressIsValid(stringString, TWCoinType(rawValue: coin.rawValue)) | |
| 35 | + } | |
| 36 | + | |
| 37 | + /// Determines if the string is a valid Any address with the given hrp. | |
| 38 | + /// | |
| 39 | + /// - Parameter string: address to validate. | |
| 40 | + /// - Parameter coin: coin type of the address. | |
| 41 | + /// - Parameter hrp: explicit given hrp of the given address. | |
| 42 | + /// - Returns: bool indicating if the address is valid. | |
| 43 | + public static func isValidBech32(string: String, coin: CoinType, hrp: String) -> Bool { | |
| 44 | + let stringString = TWStringCreateWithNSString(string) | |
| 45 | + defer { | |
| 46 | + TWStringDelete(stringString) | |
| 47 | + } | |
| 48 | + let hrpString = TWStringCreateWithNSString(hrp) | |
| 49 | + defer { | |
| 50 | + TWStringDelete(hrpString) | |
| 51 | + } | |
| 52 | + return TWAnyAddressIsValidBech32(stringString, TWCoinType(rawValue: coin.rawValue), hrpString) | |
| 53 | + } | |
| 54 | + | |
| 55 | + /// Determines if the string is a valid Any address with the given SS58 network prefix. | |
| 56 | + /// | |
| 57 | + /// - Parameter string: address to validate. | |
| 58 | + /// - Parameter coin: coin type of the address. | |
| 59 | + /// - Parameter ss58Prefix: ss58Prefix of the given address. | |
| 60 | + /// - Returns: bool indicating if the address is valid. | |
| 61 | + public static func isValidSS58(string: String, coin: CoinType, ss58Prefix: UInt32) -> Bool { | |
| 62 | + let stringString = TWStringCreateWithNSString(string) | |
| 63 | + defer { | |
| 64 | + TWStringDelete(stringString) | |
| 65 | + } | |
| 66 | + return TWAnyAddressIsValidSS58(stringString, TWCoinType(rawValue: coin.rawValue), ss58Prefix) | |
| 67 | + } | |
| 68 | + | |
| 69 | + /// Returns the address string representation. | |
| 70 | + /// | |
| 71 | + /// - Parameter address: address to get the string representation of. | |
| 72 | + public var description: String { | |
| 73 | + return TWStringNSString(TWAnyAddressDescription(rawValue)) | |
| 74 | + } | |
| 75 | + | |
| 76 | + /// Returns coin type of address. | |
| 77 | + /// | |
| 78 | + /// - Parameter address: address to get the coin type of. | |
| 79 | + public var coin: CoinType { | |
| 80 | + return CoinType(rawValue: TWAnyAddressCoin(rawValue).rawValue)! | |
| 81 | + } | |
| 82 | + | |
| 83 | + /// Returns underlaying data (public key or key hash) | |
| 84 | + /// | |
| 85 | + /// - Parameter address: address to get the data of. | |
| 86 | + public var data: Data { | |
| 87 | + return TWDataNSData(TWAnyAddressData(rawValue)) | |
| 88 | + } | |
| 89 | + | |
| 90 | + let rawValue: OpaquePointer | |
| 91 | + | |
| 92 | + init(rawValue: OpaquePointer) { | |
| 93 | + self.rawValue = rawValue | |
| 94 | + } | |
| 95 | + | |
| 96 | + public init?(string: String, coin: CoinType) { | |
| 97 | + let stringString = TWStringCreateWithNSString(string) | |
| 98 | + defer { | |
| 99 | + TWStringDelete(stringString) | |
| 100 | + } | |
| 101 | + guard let rawValue = TWAnyAddressCreateWithString(stringString, TWCoinType(rawValue: coin.rawValue)) else { | |
| 102 | + return nil | |
| 103 | + } | |
| 104 | + self.rawValue = rawValue | |
| 105 | + } | |
| 106 | + | |
| 107 | + public init?(string: String, coin: CoinType, hrp: String) { | |
| 108 | + let stringString = TWStringCreateWithNSString(string) | |
| 109 | + defer { | |
| 110 | + TWStringDelete(stringString) | |
| 111 | + } | |
| 112 | + let hrpString = TWStringCreateWithNSString(hrp) | |
| 113 | + defer { | |
| 114 | + TWStringDelete(hrpString) | |
| 115 | + } | |
| 116 | + guard let rawValue = TWAnyAddressCreateBech32(stringString, TWCoinType(rawValue: coin.rawValue), hrpString) else { | |
| 117 | + return nil | |
| 118 | + } | |
| 119 | + self.rawValue = rawValue | |
| 120 | + } | |
| 121 | + | |
| 122 | + public init?(string: String, coin: CoinType, ss58Prefix: UInt32) { | |
| 123 | + let stringString = TWStringCreateWithNSString(string) | |
| 124 | + defer { | |
| 125 | + TWStringDelete(stringString) | |
| 126 | + } | |
| 127 | + guard let rawValue = TWAnyAddressCreateSS58(stringString, TWCoinType(rawValue: coin.rawValue), ss58Prefix) else { | |
| 128 | + return nil | |
| 129 | + } | |
| 130 | + self.rawValue = rawValue | |
| 131 | + } | |
| 132 | + | |
| 133 | + public init(publicKey: PublicKey, coin: CoinType) { | |
| 134 | + rawValue = TWAnyAddressCreateWithPublicKey(publicKey.rawValue, TWCoinType(rawValue: coin.rawValue)) | |
| 135 | + } | |
| 136 | + | |
| 137 | + public init(publicKey: PublicKey, coin: CoinType, derivation: Derivation) { | |
| 138 | + rawValue = TWAnyAddressCreateWithPublicKeyDerivation(publicKey.rawValue, TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue)) | |
| 139 | + } | |
| 140 | + | |
| 141 | + public init(publicKey: PublicKey, coin: CoinType, hrp: String) { | |
| 142 | + let hrpString = TWStringCreateWithNSString(hrp) | |
| 143 | + defer { | |
| 144 | + TWStringDelete(hrpString) | |
| 145 | + } | |
| 146 | + rawValue = TWAnyAddressCreateBech32WithPublicKey(publicKey.rawValue, TWCoinType(rawValue: coin.rawValue), hrpString) | |
| 147 | + } | |
| 148 | + | |
| 149 | + public init(publicKey: PublicKey, coin: CoinType, ss58Prefix: UInt32) { | |
| 150 | + rawValue = TWAnyAddressCreateSS58WithPublicKey(publicKey.rawValue, TWCoinType(rawValue: coin.rawValue), ss58Prefix) | |
| 151 | + } | |
| 152 | + | |
| 153 | + public init(publicKey: PublicKey, filecoinAddressType: FilecoinAddressType) { | |
| 154 | + rawValue = TWAnyAddressCreateWithPublicKeyFilecoinAddressType(publicKey.rawValue, TWFilecoinAddressType(rawValue: filecoinAddressType.rawValue)) | |
| 155 | + } | |
| 156 | + | |
| 157 | + public init(publicKey: PublicKey, firoAddressType: FiroAddressType) { | |
| 158 | + rawValue = TWAnyAddressCreateWithPublicKeyFiroAddressType(publicKey.rawValue, TWFiroAddressType(rawValue: firoAddressType.rawValue)) | |
| 159 | + } | |
| 160 | + | |
| 161 | + deinit { | |
| 162 | + TWAnyAddressDelete(rawValue) | |
| 163 | + } | |
| 164 | + | |
| 165 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/AsnParser.swift
+35 −0
@@ -0,0 +1,35 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents an ASN.1 DER parser. | |
| 13 | +public struct AsnParser { | |
| 14 | + | |
| 15 | + /// Parses the given ECDSA signature from ASN.1 DER encoded bytes. | |
| 16 | + /// | |
| 17 | + /// - Parameter encoded: The ASN.1 DER encoded signature. | |
| 18 | + /// - Returns: The ECDSA signature standard binary representation: RS, where R - 32 byte array, S - 32 byte array. | |
| 19 | + public static func ecdsaSignatureFromDer(encoded: Data) -> Data? { | |
| 20 | + let encodedData = TWDataCreateWithNSData(encoded) | |
| 21 | + defer { | |
| 22 | + TWDataDelete(encodedData) | |
| 23 | + } | |
| 24 | + guard let result = TWAsnParserEcdsaSignatureFromDer(encodedData) else { | |
| 25 | + return nil | |
| 26 | + } | |
| 27 | + return TWDataNSData(result) | |
| 28 | + } | |
| 29 | + | |
| 30 | + | |
| 31 | + init() { | |
| 32 | + } | |
| 33 | + | |
| 34 | + | |
| 35 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Barz.swift
+125 −0
@@ -0,0 +1,125 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class Barz { | |
| 14 | + | |
| 15 | + /// Calculate a counterfactual address for the smart contract wallet | |
| 16 | + /// | |
| 17 | + /// - Parameter input: The serialized data of ContractAddressInput. | |
| 18 | + /// - Returns: The address. | |
| 19 | + public static func getCounterfactualAddress(input: Data) -> String? { | |
| 20 | + let inputData = TWDataCreateWithNSData(input) | |
| 21 | + defer { | |
| 22 | + TWDataDelete(inputData) | |
| 23 | + } | |
| 24 | + guard let result = TWBarzGetCounterfactualAddress(inputData) else { | |
| 25 | + return nil | |
| 26 | + } | |
| 27 | + return TWStringNSString(result) | |
| 28 | + } | |
| 29 | + | |
| 30 | + /// Returns the init code parameter of ERC-4337 User Operation | |
| 31 | + /// | |
| 32 | + /// - Parameter factory: The address of the factory contract | |
| 33 | + /// - Parameter public_key: Public key for the verification facet | |
| 34 | + /// - Parameter verification_facet: The address of the verification facet | |
| 35 | + /// - Parameter salt: The salt of the init code; Must be non-negative | |
| 36 | + /// - Returns: The init code. | |
| 37 | + public static func getInitCode(factory: String, publicKey: PublicKey, verificationFacet: String, salt: Int32) -> Data? { | |
| 38 | + let factoryString = TWStringCreateWithNSString(factory) | |
| 39 | + defer { | |
| 40 | + TWStringDelete(factoryString) | |
| 41 | + } | |
| 42 | + let verificationFacetString = TWStringCreateWithNSString(verificationFacet) | |
| 43 | + defer { | |
| 44 | + TWStringDelete(verificationFacetString) | |
| 45 | + } | |
| 46 | + guard let result = TWBarzGetInitCode(factoryString, publicKey.rawValue, verificationFacetString, salt) else { | |
| 47 | + return nil | |
| 48 | + } | |
| 49 | + return TWDataNSData(result) | |
| 50 | + } | |
| 51 | + | |
| 52 | + /// Converts the original ASN-encoded signature from webauthn to the format accepted by Barz | |
| 53 | + /// | |
| 54 | + /// - Parameter signature: Original signature | |
| 55 | + /// - Parameter challenge: The original challenge that was signed | |
| 56 | + /// - Parameter authenticator_data: Returned from Webauthn API | |
| 57 | + /// - Parameter client_data_json: Returned from Webauthn API | |
| 58 | + /// - Returns: Bytes of the formatted signature | |
| 59 | + public static func getFormattedSignature(signature: Data, challenge: Data, authenticatorData: Data, clientDataJson: String) -> Data? { | |
| 60 | + let signatureData = TWDataCreateWithNSData(signature) | |
| 61 | + defer { | |
| 62 | + TWDataDelete(signatureData) | |
| 63 | + } | |
| 64 | + let challengeData = TWDataCreateWithNSData(challenge) | |
| 65 | + defer { | |
| 66 | + TWDataDelete(challengeData) | |
| 67 | + } | |
| 68 | + let authenticatorDataData = TWDataCreateWithNSData(authenticatorData) | |
| 69 | + defer { | |
| 70 | + TWDataDelete(authenticatorDataData) | |
| 71 | + } | |
| 72 | + let clientDataJsonString = TWStringCreateWithNSString(clientDataJson) | |
| 73 | + defer { | |
| 74 | + TWStringDelete(clientDataJsonString) | |
| 75 | + } | |
| 76 | + guard let result = TWBarzGetFormattedSignature(signatureData, challengeData, authenticatorDataData, clientDataJsonString) else { | |
| 77 | + return nil | |
| 78 | + } | |
| 79 | + return TWDataNSData(result) | |
| 80 | + } | |
| 81 | + | |
| 82 | + /// Returns the final hash to be signed by Barz for signing messages & typed data | |
| 83 | + /// | |
| 84 | + /// - Parameter msg_hash: Original msgHash | |
| 85 | + /// - Parameter barzAddress: The address of Barz wallet signing the message | |
| 86 | + /// - Parameter chainId: The chainId of the network the verification will happen; Must be non-negative | |
| 87 | + /// - Returns: The final hash to be signed. | |
| 88 | + public static func getPrefixedMsgHash(msgHash: Data, barzAddress: String, chainId: Int32) -> Data? { | |
| 89 | + let msgHashData = TWDataCreateWithNSData(msgHash) | |
| 90 | + defer { | |
| 91 | + TWDataDelete(msgHashData) | |
| 92 | + } | |
| 93 | + let barzAddressString = TWStringCreateWithNSString(barzAddress) | |
| 94 | + defer { | |
| 95 | + TWStringDelete(barzAddressString) | |
| 96 | + } | |
| 97 | + guard let result = TWBarzGetPrefixedMsgHash(msgHashData, barzAddressString, chainId) else { | |
| 98 | + return nil | |
| 99 | + } | |
| 100 | + return TWDataNSData(result) | |
| 101 | + } | |
| 102 | + | |
| 103 | + /// Returns the encoded diamondCut function call for Barz contract upgrades | |
| 104 | + /// | |
| 105 | + /// - Parameter input: The serialized data of DiamondCutInput. | |
| 106 | + /// - Returns: The diamond cut code. | |
| 107 | + public static func getDiamondCutCode(input: Data) -> Data? { | |
| 108 | + let inputData = TWDataCreateWithNSData(input) | |
| 109 | + defer { | |
| 110 | + TWDataDelete(inputData) | |
| 111 | + } | |
| 112 | + guard let result = TWBarzGetDiamondCutCode(inputData) else { | |
| 113 | + return nil | |
| 114 | + } | |
| 115 | + return TWDataNSData(result) | |
| 116 | + } | |
| 117 | + | |
| 118 | + let rawValue: OpaquePointer | |
| 119 | + | |
| 120 | + init(rawValue: OpaquePointer) { | |
| 121 | + self.rawValue = rawValue | |
| 122 | + } | |
| 123 | + | |
| 124 | + | |
| 125 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Base32.swift
+102 −0
@@ -0,0 +1,102 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Base32 encode / decode functions | |
| 13 | +public struct Base32 { | |
| 14 | + | |
| 15 | + /// Decode a Base32 input with the given alphabet | |
| 16 | + /// | |
| 17 | + /// - Parameter string: Encoded base32 input to be decoded | |
| 18 | + /// - Parameter alphabet: Decode with the given alphabet, if nullptr ALPHABET_RFC4648 is used by default | |
| 19 | + /// - Returns: The decoded data, can be null. | |
| 20 | + /// - Note: ALPHABET_RFC4648 doesn't support padding in the default alphabet | |
| 21 | + public static func decodeWithAlphabet(string: String, alphabet: String?) -> Data? { | |
| 22 | + let stringString = TWStringCreateWithNSString(string) | |
| 23 | + defer { | |
| 24 | + TWStringDelete(stringString) | |
| 25 | + } | |
| 26 | + let alphabetString: UnsafeRawPointer? | |
| 27 | + if let s = alphabet { | |
| 28 | + alphabetString = TWStringCreateWithNSString(s) | |
| 29 | + } else { | |
| 30 | + alphabetString = nil | |
| 31 | + } | |
| 32 | + defer { | |
| 33 | + if let s = alphabetString { | |
| 34 | + TWStringDelete(s) | |
| 35 | + } | |
| 36 | + } | |
| 37 | + guard let result = TWBase32DecodeWithAlphabet(stringString, alphabetString) else { | |
| 38 | + return nil | |
| 39 | + } | |
| 40 | + return TWDataNSData(result) | |
| 41 | + } | |
| 42 | + | |
| 43 | + /// Decode a Base32 input with the default alphabet (ALPHABET_RFC4648) | |
| 44 | + /// | |
| 45 | + /// - Parameter string: Encoded input to be decoded | |
| 46 | + /// - Returns: The decoded data | |
| 47 | + /// - Note: Call TWBase32DecodeWithAlphabet with nullptr. | |
| 48 | + public static func decode(string: String) -> Data? { | |
| 49 | + let stringString = TWStringCreateWithNSString(string) | |
| 50 | + defer { | |
| 51 | + TWStringDelete(stringString) | |
| 52 | + } | |
| 53 | + guard let result = TWBase32Decode(stringString) else { | |
| 54 | + return nil | |
| 55 | + } | |
| 56 | + return TWDataNSData(result) | |
| 57 | + } | |
| 58 | + | |
| 59 | + /// Encode an input to Base32 with the given alphabet | |
| 60 | + /// | |
| 61 | + /// - Parameter data: Data to be encoded (raw bytes) | |
| 62 | + /// - Parameter alphabet: Encode with the given alphabet, if nullptr ALPHABET_RFC4648 is used by default | |
| 63 | + /// - Returns: The encoded data | |
| 64 | + /// - Note: ALPHABET_RFC4648 doesn't support padding in the default alphabet | |
| 65 | + public static func encodeWithAlphabet(data: Data, alphabet: String?) -> String { | |
| 66 | + let dataData = TWDataCreateWithNSData(data) | |
| 67 | + defer { | |
| 68 | + TWDataDelete(dataData) | |
| 69 | + } | |
| 70 | + let alphabetString: UnsafeRawPointer? | |
| 71 | + if let s = alphabet { | |
| 72 | + alphabetString = TWStringCreateWithNSString(s) | |
| 73 | + } else { | |
| 74 | + alphabetString = nil | |
| 75 | + } | |
| 76 | + defer { | |
| 77 | + if let s = alphabetString { | |
| 78 | + TWStringDelete(s) | |
| 79 | + } | |
| 80 | + } | |
| 81 | + return TWStringNSString(TWBase32EncodeWithAlphabet(dataData, alphabetString)) | |
| 82 | + } | |
| 83 | + | |
| 84 | + /// Encode an input to Base32 with the default alphabet (ALPHABET_RFC4648) | |
| 85 | + /// | |
| 86 | + /// - Parameter data: Data to be encoded (raw bytes) | |
| 87 | + /// - Returns: The encoded data | |
| 88 | + /// - Note: Call TWBase32EncodeWithAlphabet with nullptr. | |
| 89 | + public static func encode(data: Data) -> String { | |
| 90 | + let dataData = TWDataCreateWithNSData(data) | |
| 91 | + defer { | |
| 92 | + TWDataDelete(dataData) | |
| 93 | + } | |
| 94 | + return TWStringNSString(TWBase32Encode(dataData)) | |
| 95 | + } | |
| 96 | + | |
| 97 | + | |
| 98 | + init() { | |
| 99 | + } | |
| 100 | + | |
| 101 | + | |
| 102 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Base58.swift
+74 −0
@@ -0,0 +1,74 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Base58 encode / decode functions | |
| 13 | +public struct Base58 { | |
| 14 | + | |
| 15 | + /// Encodes data as a Base58 string, including the checksum. | |
| 16 | + /// | |
| 17 | + /// - Parameter data: The data to encode. | |
| 18 | + /// - Returns: the encoded Base58 string with checksum. | |
| 19 | + public static func encode(data: Data) -> String { | |
| 20 | + let dataData = TWDataCreateWithNSData(data) | |
| 21 | + defer { | |
| 22 | + TWDataDelete(dataData) | |
| 23 | + } | |
| 24 | + return TWStringNSString(TWBase58Encode(dataData)) | |
| 25 | + } | |
| 26 | + | |
| 27 | + /// Encodes data as a Base58 string, not including the checksum. | |
| 28 | + /// | |
| 29 | + /// - Parameter data: The data to encode. | |
| 30 | + /// - Returns: then encoded Base58 string without checksum. | |
| 31 | + public static func encodeNoCheck(data: Data) -> String { | |
| 32 | + let dataData = TWDataCreateWithNSData(data) | |
| 33 | + defer { | |
| 34 | + TWDataDelete(dataData) | |
| 35 | + } | |
| 36 | + return TWStringNSString(TWBase58EncodeNoCheck(dataData)) | |
| 37 | + } | |
| 38 | + | |
| 39 | + /// Decodes a Base58 string, checking the checksum. Returns null if the string is not a valid Base58 string. | |
| 40 | + /// | |
| 41 | + /// - Parameter string: The Base58 string to decode. | |
| 42 | + /// - Returns: the decoded data, null if the string is not a valid Base58 string with checksum. | |
| 43 | + public static func decode(string: String) -> Data? { | |
| 44 | + let stringString = TWStringCreateWithNSString(string) | |
| 45 | + defer { | |
| 46 | + TWStringDelete(stringString) | |
| 47 | + } | |
| 48 | + guard let result = TWBase58Decode(stringString) else { | |
| 49 | + return nil | |
| 50 | + } | |
| 51 | + return TWDataNSData(result) | |
| 52 | + } | |
| 53 | + | |
| 54 | + /// Decodes a Base58 string, w/o checking the checksum. Returns null if the string is not a valid Base58 string. | |
| 55 | + /// | |
| 56 | + /// - Parameter string: The Base58 string to decode. | |
| 57 | + /// - Returns: the decoded data, null if the string is not a valid Base58 string without checksum. | |
| 58 | + public static func decodeNoCheck(string: String) -> Data? { | |
| 59 | + let stringString = TWStringCreateWithNSString(string) | |
| 60 | + defer { | |
| 61 | + TWStringDelete(stringString) | |
| 62 | + } | |
| 63 | + guard let result = TWBase58DecodeNoCheck(stringString) else { | |
| 64 | + return nil | |
| 65 | + } | |
| 66 | + return TWDataNSData(result) | |
| 67 | + } | |
| 68 | + | |
| 69 | + | |
| 70 | + init() { | |
| 71 | + } | |
| 72 | + | |
| 73 | + | |
| 74 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Base64.swift
+74 −0
@@ -0,0 +1,74 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Base64 encode / decode functions | |
| 13 | +public struct Base64 { | |
| 14 | + | |
| 15 | + /// Decode a Base64 input with the default alphabet (RFC4648 with '+', '/') | |
| 16 | + /// | |
| 17 | + /// - Parameter string: Encoded input to be decoded | |
| 18 | + /// - Returns: The decoded data, empty if decoding failed. | |
| 19 | + public static func decode(string: String) -> Data? { | |
| 20 | + let stringString = TWStringCreateWithNSString(string) | |
| 21 | + defer { | |
| 22 | + TWStringDelete(stringString) | |
| 23 | + } | |
| 24 | + guard let result = TWBase64Decode(stringString) else { | |
| 25 | + return nil | |
| 26 | + } | |
| 27 | + return TWDataNSData(result) | |
| 28 | + } | |
| 29 | + | |
| 30 | + /// Decode a Base64 input with the alphabet safe for URL-s and filenames (RFC4648 with '-', '_') | |
| 31 | + /// | |
| 32 | + /// - Parameter string: Encoded base64 input to be decoded | |
| 33 | + /// - Returns: The decoded data, empty if decoding failed. | |
| 34 | + public static func decodeUrl(string: String) -> Data? { | |
| 35 | + let stringString = TWStringCreateWithNSString(string) | |
| 36 | + defer { | |
| 37 | + TWStringDelete(stringString) | |
| 38 | + } | |
| 39 | + guard let result = TWBase64DecodeUrl(stringString) else { | |
| 40 | + return nil | |
| 41 | + } | |
| 42 | + return TWDataNSData(result) | |
| 43 | + } | |
| 44 | + | |
| 45 | + /// Encode an input to Base64 with the default alphabet (RFC4648 with '+', '/') | |
| 46 | + /// | |
| 47 | + /// - Parameter data: Data to be encoded (raw bytes) | |
| 48 | + /// - Returns: The encoded data | |
| 49 | + public static func encode(data: Data) -> String { | |
| 50 | + let dataData = TWDataCreateWithNSData(data) | |
| 51 | + defer { | |
| 52 | + TWDataDelete(dataData) | |
| 53 | + } | |
| 54 | + return TWStringNSString(TWBase64Encode(dataData)) | |
| 55 | + } | |
| 56 | + | |
| 57 | + /// Encode an input to Base64 with the alphabet safe for URL-s and filenames (RFC4648 with '-', '_') | |
| 58 | + /// | |
| 59 | + /// - Parameter data: Data to be encoded (raw bytes) | |
| 60 | + /// - Returns: The encoded data | |
| 61 | + public static func encodeUrl(data: Data) -> String { | |
| 62 | + let dataData = TWDataCreateWithNSData(data) | |
| 63 | + defer { | |
| 64 | + TWDataDelete(dataData) | |
| 65 | + } | |
| 66 | + return TWStringNSString(TWBase64EncodeUrl(dataData)) | |
| 67 | + } | |
| 68 | + | |
| 69 | + | |
| 70 | + init() { | |
| 71 | + } | |
| 72 | + | |
| 73 | + | |
| 74 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Bech32.swift
+84 −0
@@ -0,0 +1,84 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Bech32 encode / decode functions | |
| 13 | +public struct Bech32 { | |
| 14 | + | |
| 15 | + /// Encodes data as a Bech32 string. | |
| 16 | + /// | |
| 17 | + /// - Parameter hrp: The human-readable part. | |
| 18 | + /// - Parameter data: The data part. | |
| 19 | + /// - Returns: the encoded Bech32 string. | |
| 20 | + public static func encode(hrp: String, data: Data) -> String { | |
| 21 | + let hrpString = TWStringCreateWithNSString(hrp) | |
| 22 | + defer { | |
| 23 | + TWStringDelete(hrpString) | |
| 24 | + } | |
| 25 | + let dataData = TWDataCreateWithNSData(data) | |
| 26 | + defer { | |
| 27 | + TWDataDelete(dataData) | |
| 28 | + } | |
| 29 | + return TWStringNSString(TWBech32Encode(hrpString, dataData)) | |
| 30 | + } | |
| 31 | + | |
| 32 | + /// Decodes a Bech32 string. Returns null if the string is not a valid Bech32 string. | |
| 33 | + /// | |
| 34 | + /// - Parameter string: The Bech32 string to decode. | |
| 35 | + /// - Returns: the decoded data, null if the string is not a valid Bech32 string. Note that the human-readable part is not returned. | |
| 36 | + public static func decode(string: String) -> Data? { | |
| 37 | + let stringString = TWStringCreateWithNSString(string) | |
| 38 | + defer { | |
| 39 | + TWStringDelete(stringString) | |
| 40 | + } | |
| 41 | + guard let result = TWBech32Decode(stringString) else { | |
| 42 | + return nil | |
| 43 | + } | |
| 44 | + return TWDataNSData(result) | |
| 45 | + } | |
| 46 | + | |
| 47 | + /// Encodes data as a Bech32m string. | |
| 48 | + /// | |
| 49 | + /// - Parameter hrp: The human-readable part. | |
| 50 | + /// - Parameter data: The data part. | |
| 51 | + /// - Returns: the encoded Bech32m string. | |
| 52 | + public static func encodeM(hrp: String, data: Data) -> String { | |
| 53 | + let hrpString = TWStringCreateWithNSString(hrp) | |
| 54 | + defer { | |
| 55 | + TWStringDelete(hrpString) | |
| 56 | + } | |
| 57 | + let dataData = TWDataCreateWithNSData(data) | |
| 58 | + defer { | |
| 59 | + TWDataDelete(dataData) | |
| 60 | + } | |
| 61 | + return TWStringNSString(TWBech32EncodeM(hrpString, dataData)) | |
| 62 | + } | |
| 63 | + | |
| 64 | + /// Decodes a Bech32m string. Returns null if the string is not a valid Bech32m string. | |
| 65 | + /// | |
| 66 | + /// - Parameter string: The Bech32m string to decode. | |
| 67 | + /// - Returns: the decoded data, null if the string is not a valid Bech32m string. Note that the human-readable part is not returned. | |
| 68 | + public static func decodeM(string: String) -> Data? { | |
| 69 | + let stringString = TWStringCreateWithNSString(string) | |
| 70 | + defer { | |
| 71 | + TWStringDelete(stringString) | |
| 72 | + } | |
| 73 | + guard let result = TWBech32DecodeM(stringString) else { | |
| 74 | + return nil | |
| 75 | + } | |
| 76 | + return TWDataNSData(result) | |
| 77 | + } | |
| 78 | + | |
| 79 | + | |
| 80 | + init() { | |
| 81 | + } | |
| 82 | + | |
| 83 | + | |
| 84 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/BitcoinAddress.swift
+108 −0
@@ -0,0 +1,108 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a legacy Bitcoin address in C++. | |
| 13 | +public final class BitcoinAddress: Address { | |
| 14 | + | |
| 15 | + /// Compares two addresses for equality. | |
| 16 | + /// | |
| 17 | + /// - Parameter lhs: The first address to compare. | |
| 18 | + /// - Parameter rhs: The second address to compare. | |
| 19 | + /// - Returns: bool indicating the addresses are equal. | |
| 20 | + public static func == (lhs: BitcoinAddress, rhs: BitcoinAddress) -> Bool { | |
| 21 | + return TWBitcoinAddressEqual(lhs.rawValue, rhs.rawValue) | |
| 22 | + } | |
| 23 | + | |
| 24 | + /// Determines if the data is a valid Bitcoin address. | |
| 25 | + /// | |
| 26 | + /// - Parameter data: data to validate. | |
| 27 | + /// - Returns: bool indicating if the address data is valid. | |
| 28 | + public static func isValid(data: Data) -> Bool { | |
| 29 | + let dataData = TWDataCreateWithNSData(data) | |
| 30 | + defer { | |
| 31 | + TWDataDelete(dataData) | |
| 32 | + } | |
| 33 | + return TWBitcoinAddressIsValid(dataData) | |
| 34 | + } | |
| 35 | + | |
| 36 | + /// Determines if the string is a valid Bitcoin address. | |
| 37 | + /// | |
| 38 | + /// - Parameter string: string to validate. | |
| 39 | + /// - Returns: bool indicating if the address string is valid. | |
| 40 | + public static func isValidString(string: String) -> Bool { | |
| 41 | + let stringString = TWStringCreateWithNSString(string) | |
| 42 | + defer { | |
| 43 | + TWStringDelete(stringString) | |
| 44 | + } | |
| 45 | + return TWBitcoinAddressIsValidString(stringString) | |
| 46 | + } | |
| 47 | + | |
| 48 | + /// Returns the address in Base58 string representation. | |
| 49 | + /// | |
| 50 | + /// - Parameter address: Address to get the string representation of. | |
| 51 | + public var description: String { | |
| 52 | + return TWStringNSString(TWBitcoinAddressDescription(rawValue)) | |
| 53 | + } | |
| 54 | + | |
| 55 | + /// Returns the address prefix. | |
| 56 | + /// | |
| 57 | + /// - Parameter address: Address to get the prefix of. | |
| 58 | + public var prefix: UInt8 { | |
| 59 | + return TWBitcoinAddressPrefix(rawValue) | |
| 60 | + } | |
| 61 | + | |
| 62 | + /// Returns the key hash data. | |
| 63 | + /// | |
| 64 | + /// - Parameter address: Address to get the keyhash data of. | |
| 65 | + public var keyhash: Data { | |
| 66 | + return TWDataNSData(TWBitcoinAddressKeyhash(rawValue)) | |
| 67 | + } | |
| 68 | + | |
| 69 | + let rawValue: OpaquePointer | |
| 70 | + | |
| 71 | + init(rawValue: OpaquePointer) { | |
| 72 | + self.rawValue = rawValue | |
| 73 | + } | |
| 74 | + | |
| 75 | + public init?(string: String) { | |
| 76 | + let stringString = TWStringCreateWithNSString(string) | |
| 77 | + defer { | |
| 78 | + TWStringDelete(stringString) | |
| 79 | + } | |
| 80 | + guard let rawValue = TWBitcoinAddressCreateWithString(stringString) else { | |
| 81 | + return nil | |
| 82 | + } | |
| 83 | + self.rawValue = rawValue | |
| 84 | + } | |
| 85 | + | |
| 86 | + public init?(data: Data) { | |
| 87 | + let dataData = TWDataCreateWithNSData(data) | |
| 88 | + defer { | |
| 89 | + TWDataDelete(dataData) | |
| 90 | + } | |
| 91 | + guard let rawValue = TWBitcoinAddressCreateWithData(dataData) else { | |
| 92 | + return nil | |
| 93 | + } | |
| 94 | + self.rawValue = rawValue | |
| 95 | + } | |
| 96 | + | |
| 97 | + public init?(publicKey: PublicKey, prefix: UInt8) { | |
| 98 | + guard let rawValue = TWBitcoinAddressCreateWithPublicKey(publicKey.rawValue, prefix) else { | |
| 99 | + return nil | |
| 100 | + } | |
| 101 | + self.rawValue = rawValue | |
| 102 | + } | |
| 103 | + | |
| 104 | + deinit { | |
| 105 | + TWBitcoinAddressDelete(rawValue) | |
| 106 | + } | |
| 107 | + | |
| 108 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/BitcoinMessageSigner.swift
+65 −0
@@ -0,0 +1,65 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Bitcoin message signing and verification. | |
| 13 | +/// | |
| 14 | +/// Bitcoin Core and some other wallets support a message signing & verification format, to create a proof (a signature) | |
| 15 | +/// that someone has access to the private keys of a specific address. | |
| 16 | +/// This feature currently works on old legacy addresses only. | |
| 17 | +public struct BitcoinMessageSigner { | |
| 18 | + | |
| 19 | + /// Sign a message. | |
| 20 | + /// | |
| 21 | + /// - Parameter privateKey:: the private key used for signing | |
| 22 | + /// - Parameter address:: the address that matches the privateKey, must be a legacy address (P2PKH) | |
| 23 | + /// - Parameter message:: A custom message which is input to the signing. | |
| 24 | + /// - Note: Address is derived assuming compressed public key format. | |
| 25 | + /// - Returns:s the signature, Base64-encoded. On invalid input empty string is returned. Returned object needs to be deleteed after use. | |
| 26 | + public static func signMessage(privateKey: PrivateKey, address: String, message: String) -> String { | |
| 27 | + let addressString = TWStringCreateWithNSString(address) | |
| 28 | + defer { | |
| 29 | + TWStringDelete(addressString) | |
| 30 | + } | |
| 31 | + let messageString = TWStringCreateWithNSString(message) | |
| 32 | + defer { | |
| 33 | + TWStringDelete(messageString) | |
| 34 | + } | |
| 35 | + return TWStringNSString(TWBitcoinMessageSignerSignMessage(privateKey.rawValue, addressString, messageString)) | |
| 36 | + } | |
| 37 | + | |
| 38 | + /// Verify signature for a message. | |
| 39 | + /// | |
| 40 | + /// - Parameter address:: address to use, only legacy is supported | |
| 41 | + /// - Parameter message:: the message signed (without prefix) | |
| 42 | + /// - Parameter signature:: in Base64-encoded form. | |
| 43 | + /// - Returns:s false on any invalid input (does not throw). | |
| 44 | + public static func verifyMessage(address: String, message: String, signature: String) -> Bool { | |
| 45 | + let addressString = TWStringCreateWithNSString(address) | |
| 46 | + defer { | |
| 47 | + TWStringDelete(addressString) | |
| 48 | + } | |
| 49 | + let messageString = TWStringCreateWithNSString(message) | |
| 50 | + defer { | |
| 51 | + TWStringDelete(messageString) | |
| 52 | + } | |
| 53 | + let signatureString = TWStringCreateWithNSString(signature) | |
| 54 | + defer { | |
| 55 | + TWStringDelete(signatureString) | |
| 56 | + } | |
| 57 | + return TWBitcoinMessageSignerVerifyMessage(addressString, messageString, signatureString) | |
| 58 | + } | |
| 59 | + | |
| 60 | + | |
| 61 | + init() { | |
| 62 | + } | |
| 63 | + | |
| 64 | + | |
| 65 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/BitcoinScript.swift
+269 −0
@@ -0,0 +1,269 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Bitcoin script manipulating functions | |
| 13 | +public final class BitcoinScript { | |
| 14 | + | |
| 15 | + /// Determines whether 2 scripts have the same content | |
| 16 | + /// | |
| 17 | + /// - Parameter lhs: Non-null pointer to the first script | |
| 18 | + /// - Parameter rhs: Non-null pointer to the second script | |
| 19 | + /// - Returns: true if both script have the same content | |
| 20 | + public static func == (lhs: BitcoinScript, rhs: BitcoinScript) -> Bool { | |
| 21 | + return TWBitcoinScriptEqual(lhs.rawValue, rhs.rawValue) | |
| 22 | + } | |
| 23 | + | |
| 24 | + /// Builds a standard 'pay to public key' script. | |
| 25 | + /// | |
| 26 | + /// - Parameter pubkey: Non-null pointer to a pubkey | |
| 27 | + /// - Note: Must be deleted with \TWBitcoinScriptDelete | |
| 28 | + /// - Returns: A pointer to the built script | |
| 29 | + public static func buildPayToPublicKey(pubkey: Data) -> BitcoinScript { | |
| 30 | + let pubkeyData = TWDataCreateWithNSData(pubkey) | |
| 31 | + defer { | |
| 32 | + TWDataDelete(pubkeyData) | |
| 33 | + } | |
| 34 | + return BitcoinScript(rawValue: TWBitcoinScriptBuildPayToPublicKey(pubkeyData)) | |
| 35 | + } | |
| 36 | + | |
| 37 | + /// Builds a standard 'pay to public key hash' script. | |
| 38 | + /// | |
| 39 | + /// - Parameter hash: Non-null pointer to a PublicKey hash | |
| 40 | + /// - Note: Must be deleted with \TWBitcoinScriptDelete | |
| 41 | + /// - Returns: A pointer to the built script | |
| 42 | + public static func buildPayToPublicKeyHash(hash: Data) -> BitcoinScript { | |
| 43 | + let hashData = TWDataCreateWithNSData(hash) | |
| 44 | + defer { | |
| 45 | + TWDataDelete(hashData) | |
| 46 | + } | |
| 47 | + return BitcoinScript(rawValue: TWBitcoinScriptBuildPayToPublicKeyHash(hashData)) | |
| 48 | + } | |
| 49 | + | |
| 50 | + /// Builds a standard 'pay to script hash' script. | |
| 51 | + /// | |
| 52 | + /// - Parameter scriptHash: Non-null pointer to a script hash | |
| 53 | + /// - Note: Must be deleted with \TWBitcoinScriptDelete | |
| 54 | + /// - Returns: A pointer to the built script | |
| 55 | + public static func buildPayToScriptHash(scriptHash: Data) -> BitcoinScript { | |
| 56 | + let scriptHashData = TWDataCreateWithNSData(scriptHash) | |
| 57 | + defer { | |
| 58 | + TWDataDelete(scriptHashData) | |
| 59 | + } | |
| 60 | + return BitcoinScript(rawValue: TWBitcoinScriptBuildPayToScriptHash(scriptHashData)) | |
| 61 | + } | |
| 62 | + | |
| 63 | + /// Builds a pay-to-witness-public-key-hash (P2WPKH) script.. | |
| 64 | + /// | |
| 65 | + /// - Parameter hash: Non-null pointer to a witness public key hash | |
| 66 | + /// - Note: Must be deleted with \TWBitcoinScriptDelete | |
| 67 | + /// - Returns: A pointer to the built script | |
| 68 | + public static func buildPayToWitnessPubkeyHash(hash: Data) -> BitcoinScript { | |
| 69 | + let hashData = TWDataCreateWithNSData(hash) | |
| 70 | + defer { | |
| 71 | + TWDataDelete(hashData) | |
| 72 | + } | |
| 73 | + return BitcoinScript(rawValue: TWBitcoinScriptBuildPayToWitnessPubkeyHash(hashData)) | |
| 74 | + } | |
| 75 | + | |
| 76 | + /// Builds a pay-to-witness-script-hash (P2WSH) script. | |
| 77 | + /// | |
| 78 | + /// - Parameter scriptHash: Non-null pointer to a script hash | |
| 79 | + /// - Note: Must be deleted with \TWBitcoinScriptDelete | |
| 80 | + /// - Returns: A pointer to the built script | |
| 81 | + public static func buildPayToWitnessScriptHash(scriptHash: Data) -> BitcoinScript { | |
| 82 | + let scriptHashData = TWDataCreateWithNSData(scriptHash) | |
| 83 | + defer { | |
| 84 | + TWDataDelete(scriptHashData) | |
| 85 | + } | |
| 86 | + return BitcoinScript(rawValue: TWBitcoinScriptBuildPayToWitnessScriptHash(scriptHashData)) | |
| 87 | + } | |
| 88 | + | |
| 89 | + /// Builds a appropriate lock script for the given address.. | |
| 90 | + /// | |
| 91 | + /// - Parameter address: Non-null pointer to an address | |
| 92 | + /// - Parameter coin: coin type | |
| 93 | + /// - Note: Must be deleted with \TWBitcoinScriptDelete | |
| 94 | + /// - Returns: A pointer to the built script | |
| 95 | + public static func lockScriptForAddress(address: String, coin: CoinType) -> BitcoinScript { | |
| 96 | + let addressString = TWStringCreateWithNSString(address) | |
| 97 | + defer { | |
| 98 | + TWStringDelete(addressString) | |
| 99 | + } | |
| 100 | + return BitcoinScript(rawValue: TWBitcoinScriptLockScriptForAddress(addressString, TWCoinType(rawValue: coin.rawValue))) | |
| 101 | + } | |
| 102 | + | |
| 103 | + /// Builds a appropriate lock script for the given address with replay. | |
| 104 | + public static func lockScriptForAddressReplay(address: String, coin: CoinType, blockHash: Data, blockHeight: Int64) -> BitcoinScript { | |
| 105 | + let addressString = TWStringCreateWithNSString(address) | |
| 106 | + defer { | |
| 107 | + TWStringDelete(addressString) | |
| 108 | + } | |
| 109 | + let blockHashData = TWDataCreateWithNSData(blockHash) | |
| 110 | + defer { | |
| 111 | + TWDataDelete(blockHashData) | |
| 112 | + } | |
| 113 | + return BitcoinScript(rawValue: TWBitcoinScriptLockScriptForAddressReplay(addressString, TWCoinType(rawValue: coin.rawValue), blockHashData, blockHeight)) | |
| 114 | + } | |
| 115 | + | |
| 116 | + /// Return the default HashType for the given coin, such as TWBitcoinSigHashTypeAll. | |
| 117 | + /// | |
| 118 | + /// - Parameter coinType: coin type | |
| 119 | + /// - Returns: default HashType for the given coin | |
| 120 | + public static func hashTypeForCoin(coinType: CoinType) -> UInt32 { | |
| 121 | + return TWBitcoinScriptHashTypeForCoin(TWCoinType(rawValue: coinType.rawValue)) | |
| 122 | + } | |
| 123 | + | |
| 124 | + /// Get size of a script | |
| 125 | + /// | |
| 126 | + /// - Parameter script: Non-null pointer to a script | |
| 127 | + /// - Returns: size of the script | |
| 128 | + public var size: Int { | |
| 129 | + return TWBitcoinScriptSize(rawValue) | |
| 130 | + } | |
| 131 | + | |
| 132 | + /// Get data of a script | |
| 133 | + /// | |
| 134 | + /// - Parameter script: Non-null pointer to a script | |
| 135 | + /// - Returns: data of the given script | |
| 136 | + public var data: Data { | |
| 137 | + return TWDataNSData(TWBitcoinScriptData(rawValue)) | |
| 138 | + } | |
| 139 | + | |
| 140 | + /// Return script hash of a script | |
| 141 | + /// | |
| 142 | + /// - Parameter script: Non-null pointer to a script | |
| 143 | + /// - Returns: script hash of the given script | |
| 144 | + public var scriptHash: Data { | |
| 145 | + return TWDataNSData(TWBitcoinScriptScriptHash(rawValue)) | |
| 146 | + } | |
| 147 | + | |
| 148 | + /// Determines whether this is a pay-to-script-hash (P2SH) script. | |
| 149 | + /// | |
| 150 | + /// - Parameter script: Non-null pointer to a script | |
| 151 | + /// - Returns: true if this is a pay-to-script-hash (P2SH) script, false otherwise | |
| 152 | + public var isPayToScriptHash: Bool { | |
| 153 | + return TWBitcoinScriptIsPayToScriptHash(rawValue) | |
| 154 | + } | |
| 155 | + | |
| 156 | + /// Determines whether this is a pay-to-witness-script-hash (P2WSH) script. | |
| 157 | + /// | |
| 158 | + /// - Parameter script: Non-null pointer to a script | |
| 159 | + /// - Returns: true if this is a pay-to-witness-script-hash (P2WSH) script, false otherwise | |
| 160 | + public var isPayToWitnessScriptHash: Bool { | |
| 161 | + return TWBitcoinScriptIsPayToWitnessScriptHash(rawValue) | |
| 162 | + } | |
| 163 | + | |
| 164 | + /// Determines whether this is a pay-to-witness-public-key-hash (P2WPKH) script. | |
| 165 | + /// | |
| 166 | + /// - Parameter script: Non-null pointer to a script | |
| 167 | + /// - Returns: true if this is a pay-to-witness-public-key-hash (P2WPKH) script, false otherwise | |
| 168 | + public var isPayToWitnessPublicKeyHash: Bool { | |
| 169 | + return TWBitcoinScriptIsPayToWitnessPublicKeyHash(rawValue) | |
| 170 | + } | |
| 171 | + | |
| 172 | + /// Determines whether this is a witness program script. | |
| 173 | + /// | |
| 174 | + /// - Parameter script: Non-null pointer to a script | |
| 175 | + /// - Returns: true if this is a witness program script, false otherwise | |
| 176 | + public var isWitnessProgram: Bool { | |
| 177 | + return TWBitcoinScriptIsWitnessProgram(rawValue) | |
| 178 | + } | |
| 179 | + | |
| 180 | + let rawValue: OpaquePointer | |
| 181 | + | |
| 182 | + init(rawValue: OpaquePointer) { | |
| 183 | + self.rawValue = rawValue | |
| 184 | + } | |
| 185 | + | |
| 186 | + public init() { | |
| 187 | + rawValue = TWBitcoinScriptCreate() | |
| 188 | + } | |
| 189 | + | |
| 190 | + public init(data: Data) { | |
| 191 | + let dataData = TWDataCreateWithNSData(data) | |
| 192 | + defer { | |
| 193 | + TWDataDelete(dataData) | |
| 194 | + } | |
| 195 | + rawValue = TWBitcoinScriptCreateWithData(dataData) | |
| 196 | + } | |
| 197 | + | |
| 198 | + public init(script: BitcoinScript) { | |
| 199 | + rawValue = TWBitcoinScriptCreateCopy(script.rawValue) | |
| 200 | + } | |
| 201 | + | |
| 202 | + deinit { | |
| 203 | + TWBitcoinScriptDelete(rawValue) | |
| 204 | + } | |
| 205 | + | |
| 206 | + /// Matches the script to a pay-to-public-key (P2PK) script. | |
| 207 | + /// | |
| 208 | + /// - Parameter script: Non-null pointer to a script | |
| 209 | + /// - Returns: The public key. | |
| 210 | + public func matchPayToPubkey() -> Data? { | |
| 211 | + guard let result = TWBitcoinScriptMatchPayToPubkey(rawValue) else { | |
| 212 | + return nil | |
| 213 | + } | |
| 214 | + return TWDataNSData(result) | |
| 215 | + } | |
| 216 | + | |
| 217 | + /// Matches the script to a pay-to-public-key-hash (P2PKH). | |
| 218 | + /// | |
| 219 | + /// - Parameter script: Non-null pointer to a script | |
| 220 | + /// - Returns: the key hash. | |
| 221 | + public func matchPayToPubkeyHash() -> Data? { | |
| 222 | + guard let result = TWBitcoinScriptMatchPayToPubkeyHash(rawValue) else { | |
| 223 | + return nil | |
| 224 | + } | |
| 225 | + return TWDataNSData(result) | |
| 226 | + } | |
| 227 | + | |
| 228 | + /// Matches the script to a pay-to-script-hash (P2SH). | |
| 229 | + /// | |
| 230 | + /// - Parameter script: Non-null pointer to a script | |
| 231 | + /// - Returns: the script hash. | |
| 232 | + public func matchPayToScriptHash() -> Data? { | |
| 233 | + guard let result = TWBitcoinScriptMatchPayToScriptHash(rawValue) else { | |
| 234 | + return nil | |
| 235 | + } | |
| 236 | + return TWDataNSData(result) | |
| 237 | + } | |
| 238 | + | |
| 239 | + /// Matches the script to a pay-to-witness-public-key-hash (P2WPKH). | |
| 240 | + /// | |
| 241 | + /// - Parameter script: Non-null pointer to a script | |
| 242 | + /// - Returns: the key hash. | |
| 243 | + public func matchPayToWitnessPublicKeyHash() -> Data? { | |
| 244 | + guard let result = TWBitcoinScriptMatchPayToWitnessPublicKeyHash(rawValue) else { | |
| 245 | + return nil | |
| 246 | + } | |
| 247 | + return TWDataNSData(result) | |
| 248 | + } | |
| 249 | + | |
| 250 | + /// Matches the script to a pay-to-witness-script-hash (P2WSH). | |
| 251 | + /// | |
| 252 | + /// - Parameter script: Non-null pointer to a script | |
| 253 | + /// - Returns: the script hash, a SHA256 of the witness script.. | |
| 254 | + public func matchPayToWitnessScriptHash() -> Data? { | |
| 255 | + guard let result = TWBitcoinScriptMatchPayToWitnessScriptHash(rawValue) else { | |
| 256 | + return nil | |
| 257 | + } | |
| 258 | + return TWDataNSData(result) | |
| 259 | + } | |
| 260 | + | |
| 261 | + /// Encodes the script. | |
| 262 | + /// | |
| 263 | + /// - Parameter script: Non-null pointer to a script | |
| 264 | + /// - Returns: The encoded script | |
| 265 | + public func encode() -> Data { | |
| 266 | + return TWDataNSData(TWBitcoinScriptEncode(rawValue)) | |
| 267 | + } | |
| 268 | + | |
| 269 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/BitcoinSigHashType+Extension.swift
+29 −0
@@ -0,0 +1,29 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +extension BitcoinSigHashType { | |
| 11 | + | |
| 12 | + /// Determines if the given sig hash is single | |
| 13 | + /// | |
| 14 | + /// - Parameter type: sig hash type | |
| 15 | + /// - Returns: true if the sigh hash type is single, false otherwise | |
| 16 | + public func isSingle() -> Bool { | |
| 17 | + return TWBitcoinSigHashTypeIsSingle(TWBitcoinSigHashType(rawValue: rawValue)) | |
| 18 | + } | |
| 19 | + | |
| 20 | + | |
| 21 | + /// Determines if the given sig hash is none | |
| 22 | + /// | |
| 23 | + /// - Parameter type: sig hash type | |
| 24 | + /// - Returns: true if the sigh hash type is none, false otherwise | |
| 25 | + public func isNone() -> Bool { | |
| 26 | + return TWBitcoinSigHashTypeIsNone(TWBitcoinSigHashType(rawValue: rawValue)) | |
| 27 | + } | |
| 28 | + | |
| 29 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Biz.swift
+107 −0
@@ -0,0 +1,107 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class Biz { | |
| 14 | + | |
| 15 | + /// Returns the encoded hash of the user operation | |
| 16 | + /// | |
| 17 | + /// - Parameter chain_id: The chain ID of the user. | |
| 18 | + /// - Parameter code_address: The address of the smart contract wallet. | |
| 19 | + /// - Parameter code_name: The name of the smart contract wallet. | |
| 20 | + /// - Parameter code_version: The version of the smart contract wallet. | |
| 21 | + /// - Parameter type_hash: The type hash of the smart contract wallet. | |
| 22 | + /// - Parameter domain_separator_hash: The domain separator hash of the smart contract wallet. | |
| 23 | + /// - Parameter sender: The sender of the smart contract wallet. | |
| 24 | + /// - Parameter user_op_hash: The user operation hash of the smart contract wallet. | |
| 25 | + /// - Returns: The encoded hash. | |
| 26 | + public static func getEncodedHash(chainId: Data, codeAddress: String, codeName: String, codeVersion: String, typeHash: String, domainSeparatorHash: String, sender: String, userOpHash: String) -> Data? { | |
| 27 | + let chainIdData = TWDataCreateWithNSData(chainId) | |
| 28 | + defer { | |
| 29 | + TWDataDelete(chainIdData) | |
| 30 | + } | |
| 31 | + let codeAddressString = TWStringCreateWithNSString(codeAddress) | |
| 32 | + defer { | |
| 33 | + TWStringDelete(codeAddressString) | |
| 34 | + } | |
| 35 | + let codeNameString = TWStringCreateWithNSString(codeName) | |
| 36 | + defer { | |
| 37 | + TWStringDelete(codeNameString) | |
| 38 | + } | |
| 39 | + let codeVersionString = TWStringCreateWithNSString(codeVersion) | |
| 40 | + defer { | |
| 41 | + TWStringDelete(codeVersionString) | |
| 42 | + } | |
| 43 | + let typeHashString = TWStringCreateWithNSString(typeHash) | |
| 44 | + defer { | |
| 45 | + TWStringDelete(typeHashString) | |
| 46 | + } | |
| 47 | + let domainSeparatorHashString = TWStringCreateWithNSString(domainSeparatorHash) | |
| 48 | + defer { | |
| 49 | + TWStringDelete(domainSeparatorHashString) | |
| 50 | + } | |
| 51 | + let senderString = TWStringCreateWithNSString(sender) | |
| 52 | + defer { | |
| 53 | + TWStringDelete(senderString) | |
| 54 | + } | |
| 55 | + let userOpHashString = TWStringCreateWithNSString(userOpHash) | |
| 56 | + defer { | |
| 57 | + TWStringDelete(userOpHashString) | |
| 58 | + } | |
| 59 | + guard let result = TWBizGetEncodedHash(chainIdData, codeAddressString, codeNameString, codeVersionString, typeHashString, domainSeparatorHashString, senderString, userOpHashString) else { | |
| 60 | + return nil | |
| 61 | + } | |
| 62 | + return TWDataNSData(result) | |
| 63 | + } | |
| 64 | + | |
| 65 | + /// Signs a message using the private key | |
| 66 | + /// | |
| 67 | + /// - Parameter hash: The hash of the user. | |
| 68 | + /// - Parameter private_key: The private key of the user. | |
| 69 | + /// - Returns: The signed hash. | |
| 70 | + public static func getSignedHash(hash: String, privateKey: String) -> Data? { | |
| 71 | + let hashString = TWStringCreateWithNSString(hash) | |
| 72 | + defer { | |
| 73 | + TWStringDelete(hashString) | |
| 74 | + } | |
| 75 | + let privateKeyString = TWStringCreateWithNSString(privateKey) | |
| 76 | + defer { | |
| 77 | + TWStringDelete(privateKeyString) | |
| 78 | + } | |
| 79 | + guard let result = TWBizGetSignedHash(hashString, privateKeyString) else { | |
| 80 | + return nil | |
| 81 | + } | |
| 82 | + return TWDataNSData(result) | |
| 83 | + } | |
| 84 | + | |
| 85 | + /// Signs and encodes `Biz.executeWithPasskeySession` function call to execute a batch of transactions. | |
| 86 | + /// | |
| 87 | + /// - Parameter input: The serialized data of `Biz.ExecuteWithSignatureInput` protobuf message. | |
| 88 | + /// - Returns: ABI-encoded function call. | |
| 89 | + public static func signExecuteWithSignatureCall(input: Data) -> Data? { | |
| 90 | + let inputData = TWDataCreateWithNSData(input) | |
| 91 | + defer { | |
| 92 | + TWDataDelete(inputData) | |
| 93 | + } | |
| 94 | + guard let result = TWBizSignExecuteWithSignatureCall(inputData) else { | |
| 95 | + return nil | |
| 96 | + } | |
| 97 | + return TWDataNSData(result) | |
| 98 | + } | |
| 99 | + | |
| 100 | + let rawValue: OpaquePointer | |
| 101 | + | |
| 102 | + init(rawValue: OpaquePointer) { | |
| 103 | + self.rawValue = rawValue | |
| 104 | + } | |
| 105 | + | |
| 106 | + | |
| 107 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/BizPasskeySession.swift
+94 −0
@@ -0,0 +1,94 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class BizPasskeySession { | |
| 14 | + | |
| 15 | + /// Encodes `BizPasskeySession.registerSession` function call to register a session passkey public key. | |
| 16 | + /// | |
| 17 | + /// - Parameter session_passkey_public_key: The nist256p1 (aka secp256p1) public key of the session passkey. | |
| 18 | + /// - Parameter valid_until_timestamp: The timestamp until which the session is valid. Big endian uint64. | |
| 19 | + /// - Returns: ABI-encoded function call. | |
| 20 | + public static func encodeRegisterSessionCall(sessionPasskeyPublicKey: PublicKey, validUntilTimestamp: Data) -> Data? { | |
| 21 | + let validUntilTimestampData = TWDataCreateWithNSData(validUntilTimestamp) | |
| 22 | + defer { | |
| 23 | + TWDataDelete(validUntilTimestampData) | |
| 24 | + } | |
| 25 | + guard let result = TWBizPasskeySessionEncodeRegisterSessionCall(sessionPasskeyPublicKey.rawValue, validUntilTimestampData) else { | |
| 26 | + return nil | |
| 27 | + } | |
| 28 | + return TWDataNSData(result) | |
| 29 | + } | |
| 30 | + | |
| 31 | + /// Encodes `BizPasskeySession.removeSession` function call to deregister a session passkey public key. | |
| 32 | + /// | |
| 33 | + /// - Parameter session_passkey_public_key: The nist256p1 (aka secp256p1) public key of the session passkey. | |
| 34 | + /// - Returns: ABI-encoded function call. | |
| 35 | + public static func encodeRemoveSessionCall(sessionPasskeyPublicKey: PublicKey) -> Data? { | |
| 36 | + guard let result = TWBizPasskeySessionEncodeRemoveSessionCall(sessionPasskeyPublicKey.rawValue) else { | |
| 37 | + return nil | |
| 38 | + } | |
| 39 | + return TWDataNSData(result) | |
| 40 | + } | |
| 41 | + | |
| 42 | + /// Encodes `BizPasskeySession` nonce. | |
| 43 | + /// | |
| 44 | + /// - Parameter nonce: The nonce of the Biz Passkey Session account. | |
| 45 | + /// - Returns: uint256 represented as [passkey_nonce_key_192, nonce_64]. | |
| 46 | + public static func encodePasskeySessionNonce(nonce: Data) -> Data? { | |
| 47 | + let nonceData = TWDataCreateWithNSData(nonce) | |
| 48 | + defer { | |
| 49 | + TWDataDelete(nonceData) | |
| 50 | + } | |
| 51 | + guard let result = TWBizPasskeySessionEncodePasskeySessionNonce(nonceData) else { | |
| 52 | + return nil | |
| 53 | + } | |
| 54 | + return TWDataNSData(result) | |
| 55 | + } | |
| 56 | + | |
| 57 | + /// Signs and encodes `BizPasskeySession.executeWithPasskeySession` function call to execute a batch of transactions. | |
| 58 | + /// | |
| 59 | + /// - Parameter input: The serialized data of `BizPasskeySession.ExecuteWithSignatureInput` protobuf message. | |
| 60 | + /// - Returns: ABI-encoded function call. | |
| 61 | + public static func signExecuteWithSignatureCall(input: Data) -> Data? { | |
| 62 | + let inputData = TWDataCreateWithNSData(input) | |
| 63 | + defer { | |
| 64 | + TWDataDelete(inputData) | |
| 65 | + } | |
| 66 | + guard let result = TWBizPasskeySessionSignExecuteWithSignatureCall(inputData) else { | |
| 67 | + return nil | |
| 68 | + } | |
| 69 | + return TWDataNSData(result) | |
| 70 | + } | |
| 71 | + | |
| 72 | + /// Encodes `BizPasskeySession.executeWithPasskeySession` function call to execute a batch of transactions. | |
| 73 | + /// | |
| 74 | + /// - Parameter input: The serialized data of `BizPasskeySession.ExecuteWithPasskeySessionInput` protobuf message. | |
| 75 | + /// - Returns: ABI-encoded function call. | |
| 76 | + public static func encodeExecuteWithPasskeySessionCall(input: Data) -> Data? { | |
| 77 | + let inputData = TWDataCreateWithNSData(input) | |
| 78 | + defer { | |
| 79 | + TWDataDelete(inputData) | |
| 80 | + } | |
| 81 | + guard let result = TWBizPasskeySessionEncodeExecuteWithPasskeySessionCall(inputData) else { | |
| 82 | + return nil | |
| 83 | + } | |
| 84 | + return TWDataNSData(result) | |
| 85 | + } | |
| 86 | + | |
| 87 | + let rawValue: OpaquePointer | |
| 88 | + | |
| 89 | + init(rawValue: OpaquePointer) { | |
| 90 | + self.rawValue = rawValue | |
| 91 | + } | |
| 92 | + | |
| 93 | + | |
| 94 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Cardano.swift
+79 −0
@@ -0,0 +1,79 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Cardano helper functions | |
| 13 | +public struct Cardano { | |
| 14 | + | |
| 15 | + /// Calculates the minimum ADA amount needed for a UTXO. | |
| 16 | + /// | |
| 17 | + /// \deprecated consider using `TWCardanoOutputMinAdaAmount` instead. | |
| 18 | + /// - SeeAlso: reference https://docs.cardano.org/native-tokens/minimum-ada-value-requirement | |
| 19 | + /// - Parameter tokenBundle: serialized data of TW.Cardano.Proto.TokenBundle. | |
| 20 | + /// - Returns: the minimum ADA amount. | |
| 21 | + public static func minAdaAmount(tokenBundle: Data) -> UInt64 { | |
| 22 | + let tokenBundleData = TWDataCreateWithNSData(tokenBundle) | |
| 23 | + defer { | |
| 24 | + TWDataDelete(tokenBundleData) | |
| 25 | + } | |
| 26 | + return TWCardanoMinAdaAmount(tokenBundleData) | |
| 27 | + } | |
| 28 | + | |
| 29 | + /// Calculates the minimum ADA amount needed for an output. | |
| 30 | + /// | |
| 31 | + /// - SeeAlso: reference https://docs.cardano.org/native-tokens/minimum-ada-value-requirement | |
| 32 | + /// - Parameter toAddress: valid destination address, as string. | |
| 33 | + /// - Parameter tokenBundle: serialized data of TW.Cardano.Proto.TokenBundle. | |
| 34 | + /// - Parameter coinsPerUtxoByte: cost per one byte of a serialized UTXO (Base-10 decimal string). | |
| 35 | + /// - Returns: the minimum ADA amount (Base-10 decimal string). | |
| 36 | + public static func outputMinAdaAmount(toAddress: String, tokenBundle: Data, coinsPerUtxoByte: String) -> String? { | |
| 37 | + let toAddressString = TWStringCreateWithNSString(toAddress) | |
| 38 | + defer { | |
| 39 | + TWStringDelete(toAddressString) | |
| 40 | + } | |
| 41 | + let tokenBundleData = TWDataCreateWithNSData(tokenBundle) | |
| 42 | + defer { | |
| 43 | + TWDataDelete(tokenBundleData) | |
| 44 | + } | |
| 45 | + let coinsPerUtxoByteString = TWStringCreateWithNSString(coinsPerUtxoByte) | |
| 46 | + defer { | |
| 47 | + TWStringDelete(coinsPerUtxoByteString) | |
| 48 | + } | |
| 49 | + guard let result = TWCardanoOutputMinAdaAmount(toAddressString, tokenBundleData, coinsPerUtxoByteString) else { | |
| 50 | + return nil | |
| 51 | + } | |
| 52 | + return TWStringNSString(result) | |
| 53 | + } | |
| 54 | + | |
| 55 | + /// Return the staking address associated to (contained in) this address. Must be a Base address. | |
| 56 | + /// Empty string is returned on error. Result must be freed. | |
| 57 | + /// - Parameter baseAddress: A valid base address, as string. | |
| 58 | + /// - Returns: the associated staking (reward) address, as string, or empty string on error. | |
| 59 | + public static func getStakingAddress(baseAddress: String) -> String { | |
| 60 | + let baseAddressString = TWStringCreateWithNSString(baseAddress) | |
| 61 | + defer { | |
| 62 | + TWStringDelete(baseAddressString) | |
| 63 | + } | |
| 64 | + return TWStringNSString(TWCardanoGetStakingAddress(baseAddressString)) | |
| 65 | + } | |
| 66 | + | |
| 67 | + /// Return the legacy(byron) address. | |
| 68 | + /// - Parameter publicKey: A valid public key with TWPublicKeyTypeED25519Cardano type. | |
| 69 | + /// - Returns: the legacy(byron) address, as string, or empty string on error. | |
| 70 | + public static func getByronAddress(publicKey: PublicKey) -> String { | |
| 71 | + return TWStringNSString(TWCardanoGetByronAddress(publicKey.rawValue)) | |
| 72 | + } | |
| 73 | + | |
| 74 | + | |
| 75 | + init() { | |
| 76 | + } | |
| 77 | + | |
| 78 | + | |
| 79 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/CoinType+Extension.swift
+162 −0
@@ -0,0 +1,162 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +extension CoinType { | |
| 11 | + /// Returns the blockchain for a coin type. | |
| 12 | + /// | |
| 13 | + /// - Parameter coin: A coin type | |
| 14 | + /// - Returns: blockchain associated to the given coin type | |
| 15 | + public var blockchain: Blockchain { | |
| 16 | + return Blockchain(rawValue: TWCoinTypeBlockchain(TWCoinType(rawValue: rawValue)).rawValue)! | |
| 17 | + } | |
| 18 | + /// Returns the purpose for a coin type. | |
| 19 | + /// | |
| 20 | + /// - Parameter coin: A coin type | |
| 21 | + /// - Returns: purpose associated to the given coin type | |
| 22 | + public var purpose: Purpose { | |
| 23 | + return Purpose(rawValue: TWCoinTypePurpose(TWCoinType(rawValue: rawValue)).rawValue)! | |
| 24 | + } | |
| 25 | + /// Returns the curve that should be used for a coin type. | |
| 26 | + /// | |
| 27 | + /// - Parameter coin: A coin type | |
| 28 | + /// - Returns: curve that should be used for the given coin type | |
| 29 | + public var curve: Curve { | |
| 30 | + return Curve(rawValue: TWCoinTypeCurve(TWCoinType(rawValue: rawValue)).rawValue)! | |
| 31 | + } | |
| 32 | + /// Returns the xpub HD version that should be used for a coin type. | |
| 33 | + /// | |
| 34 | + /// - Parameter coin: A coin type | |
| 35 | + /// - Returns: xpub HD version that should be used for the given coin type | |
| 36 | + public var xpubVersion: HDVersion { | |
| 37 | + return HDVersion(rawValue: TWCoinTypeXpubVersion(TWCoinType(rawValue: rawValue)).rawValue)! | |
| 38 | + } | |
| 39 | + /// Returns the xprv HD version that should be used for a coin type. | |
| 40 | + /// | |
| 41 | + /// - Parameter coin: A coin type | |
| 42 | + /// - Returns: the xprv HD version that should be used for the given coin type. | |
| 43 | + public var xprvVersion: HDVersion { | |
| 44 | + return HDVersion(rawValue: TWCoinTypeXprvVersion(TWCoinType(rawValue: rawValue)).rawValue)! | |
| 45 | + } | |
| 46 | + /// HRP for this coin type | |
| 47 | + /// | |
| 48 | + /// - Parameter coin: A coin type | |
| 49 | + /// - Returns: HRP of the given coin type. | |
| 50 | + public var hrp: HRP { | |
| 51 | + return HRP(rawValue: TWCoinTypeHRP(TWCoinType(rawValue: rawValue)).rawValue)! | |
| 52 | + } | |
| 53 | + /// P2PKH prefix for this coin type | |
| 54 | + /// | |
| 55 | + /// - Parameter coin: A coin type | |
| 56 | + /// - Returns: P2PKH prefix for the given coin type | |
| 57 | + public var p2pkhPrefix: UInt8 { | |
| 58 | + return TWCoinTypeP2pkhPrefix(TWCoinType(rawValue: rawValue)) | |
| 59 | + } | |
| 60 | + /// P2SH prefix for this coin type | |
| 61 | + /// | |
| 62 | + /// - Parameter coin: A coin type | |
| 63 | + /// - Returns: P2SH prefix for the given coin type | |
| 64 | + public var p2shPrefix: UInt8 { | |
| 65 | + return TWCoinTypeP2shPrefix(TWCoinType(rawValue: rawValue)) | |
| 66 | + } | |
| 67 | + /// Static prefix for this coin type | |
| 68 | + /// | |
| 69 | + /// - Parameter coin: A coin type | |
| 70 | + /// - Returns: Static prefix for the given coin type | |
| 71 | + public var staticPrefix: UInt8 { | |
| 72 | + return TWCoinTypeStaticPrefix(TWCoinType(rawValue: rawValue)) | |
| 73 | + } | |
| 74 | + /// ChainID for this coin type. | |
| 75 | + /// | |
| 76 | + /// - Parameter coin: A coin type | |
| 77 | + /// - Returns: ChainID for the given coin type. | |
| 78 | + /// - Note: Caller must free returned object. | |
| 79 | + public var chainId: String { | |
| 80 | + return TWStringNSString(TWCoinTypeChainId(TWCoinType(rawValue: rawValue))) | |
| 81 | + } | |
| 82 | + /// SLIP-0044 id for this coin type | |
| 83 | + /// | |
| 84 | + /// - Parameter coin: A coin type | |
| 85 | + /// - Returns: SLIP-0044 id for the given coin type | |
| 86 | + public var slip44Id: UInt32 { | |
| 87 | + return TWCoinTypeSlip44Id(TWCoinType(rawValue: rawValue)) | |
| 88 | + } | |
| 89 | + /// SS58Prefix for this coin type | |
| 90 | + /// | |
| 91 | + /// - Parameter coin: A coin type | |
| 92 | + /// - Returns: SS58Prefix for the given coin type | |
| 93 | + public var ss58Prefix: UInt32 { | |
| 94 | + return TWCoinTypeSS58Prefix(TWCoinType(rawValue: rawValue)) | |
| 95 | + } | |
| 96 | + /// public key type for this coin type | |
| 97 | + /// | |
| 98 | + /// - Parameter coin: A coin type | |
| 99 | + /// - Returns: public key type for the given coin type | |
| 100 | + public var publicKeyType: PublicKeyType { | |
| 101 | + return PublicKeyType(rawValue: TWCoinTypePublicKeyType(TWCoinType(rawValue: rawValue)).rawValue)! | |
| 102 | + } | |
| 103 | + | |
| 104 | + /// Validates an address string. | |
| 105 | + /// | |
| 106 | + /// - Parameter coin: A coin type | |
| 107 | + /// - Parameter address: A public address | |
| 108 | + /// - Returns: true if the address is a valid public address of the given coin, false otherwise. | |
| 109 | + public func validate(address: String) -> Bool { | |
| 110 | + let addressString = TWStringCreateWithNSString(address) | |
| 111 | + defer { | |
| 112 | + TWStringDelete(addressString) | |
| 113 | + } | |
| 114 | + return TWCoinTypeValidate(TWCoinType(rawValue: rawValue), addressString) | |
| 115 | + } | |
| 116 | + | |
| 117 | + | |
| 118 | + /// Returns the default derivation path for a particular coin. | |
| 119 | + /// | |
| 120 | + /// - Parameter coin: A coin type | |
| 121 | + /// - Returns: the default derivation path for the given coin type. | |
| 122 | + public func derivationPath() -> String { | |
| 123 | + return TWStringNSString(TWCoinTypeDerivationPath(TWCoinType(rawValue: rawValue))) | |
| 124 | + } | |
| 125 | + | |
| 126 | + | |
| 127 | + /// Returns the derivation path for a particular coin with the explicit given derivation. | |
| 128 | + /// | |
| 129 | + /// - Parameter coin: A coin type | |
| 130 | + /// - Parameter derivation: A derivation type | |
| 131 | + /// - Returns: the derivation path for the given coin with the explicit given derivation | |
| 132 | + public func derivationPathWithDerivation(derivation: Derivation) -> String { | |
| 133 | + return TWStringNSString(TWCoinTypeDerivationPathWithDerivation(TWCoinType(rawValue: rawValue), TWDerivation(rawValue: derivation.rawValue))) | |
| 134 | + } | |
| 135 | + | |
| 136 | + | |
| 137 | + /// Derives the address for a particular coin from the private key. | |
| 138 | + /// | |
| 139 | + /// - Parameter coin: A coin type | |
| 140 | + /// - Parameter privateKey: A valid private key | |
| 141 | + /// - Returns: Derived address for the given coin from the private key. | |
| 142 | + public func deriveAddress(privateKey: PrivateKey) -> String { | |
| 143 | + return TWStringNSString(TWCoinTypeDeriveAddress(TWCoinType(rawValue: rawValue), privateKey.rawValue)) | |
| 144 | + } | |
| 145 | + | |
| 146 | + | |
| 147 | + /// Derives the address for a particular coin from the public key. | |
| 148 | + /// | |
| 149 | + /// - Parameter coin: A coin type | |
| 150 | + /// - Parameter publicKey: A valid public key | |
| 151 | + /// - Returns: Derived address for the given coin from the public key. | |
| 152 | + public func deriveAddressFromPublicKey(publicKey: PublicKey) -> String { | |
| 153 | + return TWStringNSString(TWCoinTypeDeriveAddressFromPublicKey(TWCoinType(rawValue: rawValue), publicKey.rawValue)) | |
| 154 | + } | |
| 155 | + | |
| 156 | + | |
| 157 | + /// Derives the address for a particular coin from the public key with the derivation. | |
| 158 | + public func deriveAddressFromPublicKeyAndDerivation(publicKey: PublicKey, derivation: Derivation) -> String { | |
| 159 | + return TWStringNSString(TWCoinTypeDeriveAddressFromPublicKeyAndDerivation(TWCoinType(rawValue: rawValue), publicKey.rawValue, TWDerivation(rawValue: derivation.rawValue))) | |
| 160 | + } | |
| 161 | + | |
| 162 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/CoinTypeConfiguration.swift
+87 −0
@@ -0,0 +1,87 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// CoinTypeConfiguration functions | |
| 13 | +public struct CoinTypeConfiguration { | |
| 14 | + | |
| 15 | + /// Returns stock symbol of coin | |
| 16 | + /// | |
| 17 | + /// - Parameter type: A coin type | |
| 18 | + /// - Returns: A non-null TWString stock symbol of coin | |
| 19 | + /// - Note: Caller must free returned object | |
| 20 | + public static func getSymbol(type: CoinType) -> String { | |
| 21 | + return TWStringNSString(TWCoinTypeConfigurationGetSymbol(TWCoinType(rawValue: type.rawValue))) | |
| 22 | + } | |
| 23 | + | |
| 24 | + /// Returns max count decimal places for minimal coin unit | |
| 25 | + /// | |
| 26 | + /// - Parameter type: A coin type | |
| 27 | + /// - Returns: Returns max count decimal places for minimal coin unit | |
| 28 | + public static func getDecimals(type: CoinType) -> Int32 { | |
| 29 | + return TWCoinTypeConfigurationGetDecimals(TWCoinType(rawValue: type.rawValue)) | |
| 30 | + } | |
| 31 | + | |
| 32 | + /// Returns transaction url in blockchain explorer | |
| 33 | + /// | |
| 34 | + /// - Parameter type: A coin type | |
| 35 | + /// - Parameter transactionID: A transaction identifier | |
| 36 | + /// - Returns: Returns a non-null TWString transaction url in blockchain explorer | |
| 37 | + public static func getTransactionURL(type: CoinType, transactionID: String) -> String { | |
| 38 | + let transactionIDString = TWStringCreateWithNSString(transactionID) | |
| 39 | + defer { | |
| 40 | + TWStringDelete(transactionIDString) | |
| 41 | + } | |
| 42 | + return TWStringNSString(TWCoinTypeConfigurationGetTransactionURL(TWCoinType(rawValue: type.rawValue), transactionIDString)) | |
| 43 | + } | |
| 44 | + | |
| 45 | + /// Returns account url in blockchain explorer | |
| 46 | + /// | |
| 47 | + /// - Parameter type: A coin type | |
| 48 | + /// - Parameter accountID: an Account identifier | |
| 49 | + /// - Returns: Returns a non-null TWString account url in blockchain explorer | |
| 50 | + public static func getAccountURL(type: CoinType, accountID: String) -> String { | |
| 51 | + let accountIDString = TWStringCreateWithNSString(accountID) | |
| 52 | + defer { | |
| 53 | + TWStringDelete(accountIDString) | |
| 54 | + } | |
| 55 | + return TWStringNSString(TWCoinTypeConfigurationGetAccountURL(TWCoinType(rawValue: type.rawValue), accountIDString)) | |
| 56 | + } | |
| 57 | + | |
| 58 | + /// Returns full name of coin in lower case | |
| 59 | + /// | |
| 60 | + /// - Parameter type: A coin type | |
| 61 | + /// - Returns: Returns a non-null TWString, full name of coin in lower case | |
| 62 | + public static func getID(type: CoinType) -> String { | |
| 63 | + return TWStringNSString(TWCoinTypeConfigurationGetID(TWCoinType(rawValue: type.rawValue))) | |
| 64 | + } | |
| 65 | + | |
| 66 | + /// Returns full name of coin | |
| 67 | + /// | |
| 68 | + /// - Parameter type: A coin type | |
| 69 | + /// - Returns: Returns a non-null TWString, full name of coin | |
| 70 | + public static func getName(type: CoinType) -> String { | |
| 71 | + return TWStringNSString(TWCoinTypeConfigurationGetName(TWCoinType(rawValue: type.rawValue))) | |
| 72 | + } | |
| 73 | + | |
| 74 | + /// Returns native token name of coin | |
| 75 | + /// | |
| 76 | + /// - Parameter type: A coin type | |
| 77 | + /// - Returns: Returns a non-null TWString, native token name of coin | |
| 78 | + public static func getNativeTokenName(type: CoinType) -> String { | |
| 79 | + return TWStringNSString(TWCoinTypeConfigurationGetNativeTokenName(TWCoinType(rawValue: type.rawValue))) | |
| 80 | + } | |
| 81 | + | |
| 82 | + | |
| 83 | + init() { | |
| 84 | + } | |
| 85 | + | |
| 86 | + | |
| 87 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/CryptoBox.swift
+54 −0
@@ -0,0 +1,54 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// `crypto_box` encryption algorithms. | |
| 13 | +public struct CryptoBox { | |
| 14 | + | |
| 15 | + /// Encrypts message using `my_secret` and `other_pubkey`. | |
| 16 | + /// The output will have a randomly generated nonce prepended to it. | |
| 17 | + /// The output will be Overhead + 24 bytes longer than the original. | |
| 18 | + /// | |
| 19 | + /// - Parameter mySecret: *non-null* pointer to my secret key. | |
| 20 | + /// - Parameter otherPubkey: *non-null* pointer to other's public key. | |
| 21 | + /// - Parameter message: *non-null* pointer to the message to be encrypted. | |
| 22 | + /// - Returns: *nullable* pointer to the encrypted message with randomly generated nonce prepended to it. | |
| 23 | + public static func encryptEasy(mySecret: CryptoBoxSecretKey, otherPubkey: CryptoBoxPublicKey, message: Data) -> Data { | |
| 24 | + let messageData = TWDataCreateWithNSData(message) | |
| 25 | + defer { | |
| 26 | + TWDataDelete(messageData) | |
| 27 | + } | |
| 28 | + return TWDataNSData(TWCryptoBoxEncryptEasy(mySecret.rawValue, otherPubkey.rawValue, messageData)) | |
| 29 | + } | |
| 30 | + | |
| 31 | + /// Decrypts box produced by `TWCryptoBoxEncryptEasy`. | |
| 32 | + /// We assume a 24-byte nonce is prepended to the encrypted text in box. | |
| 33 | + /// | |
| 34 | + /// - Parameter mySecret: *non-null* pointer to my secret key. | |
| 35 | + /// - Parameter otherPubkey: *non-null* pointer to other's public key. | |
| 36 | + /// - Parameter encrypted: *non-null* pointer to the encrypted message with nonce prepended to it. | |
| 37 | + /// - Returns: *nullable* pointer to the decrypted message. | |
| 38 | + public static func decryptEasy(mySecret: CryptoBoxSecretKey, otherPubkey: CryptoBoxPublicKey, encrypted: Data) -> Data? { | |
| 39 | + let encryptedData = TWDataCreateWithNSData(encrypted) | |
| 40 | + defer { | |
| 41 | + TWDataDelete(encryptedData) | |
| 42 | + } | |
| 43 | + guard let result = TWCryptoBoxDecryptEasy(mySecret.rawValue, otherPubkey.rawValue, encryptedData) else { | |
| 44 | + return nil | |
| 45 | + } | |
| 46 | + return TWDataNSData(result) | |
| 47 | + } | |
| 48 | + | |
| 49 | + | |
| 50 | + init() { | |
| 51 | + } | |
| 52 | + | |
| 53 | + | |
| 54 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/CryptoBoxPublicKey.swift
+56 −0
@@ -0,0 +1,56 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class CryptoBoxPublicKey { | |
| 14 | + | |
| 15 | + /// Determines if the given public key is valid or not. | |
| 16 | + /// | |
| 17 | + /// - Parameter data: *non-null* byte array. | |
| 18 | + /// - Returns: true if the public key is valid, false otherwise. | |
| 19 | + public static func isValid(data: Data) -> Bool { | |
| 20 | + let dataData = TWDataCreateWithNSData(data) | |
| 21 | + defer { | |
| 22 | + TWDataDelete(dataData) | |
| 23 | + } | |
| 24 | + return TWCryptoBoxPublicKeyIsValid(dataData) | |
| 25 | + } | |
| 26 | + | |
| 27 | + /// Returns the raw data of a given public-key. | |
| 28 | + /// | |
| 29 | + /// - Parameter public_key: *non-null* pointer to a public key. | |
| 30 | + /// - Returns: C-compatible result with a C-compatible byte array. | |
| 31 | + public var data: Data { | |
| 32 | + return TWDataNSData(TWCryptoBoxPublicKeyData(rawValue)) | |
| 33 | + } | |
| 34 | + | |
| 35 | + let rawValue: OpaquePointer | |
| 36 | + | |
| 37 | + init(rawValue: OpaquePointer) { | |
| 38 | + self.rawValue = rawValue | |
| 39 | + } | |
| 40 | + | |
| 41 | + public init?(data: Data) { | |
| 42 | + let dataData = TWDataCreateWithNSData(data) | |
| 43 | + defer { | |
| 44 | + TWDataDelete(dataData) | |
| 45 | + } | |
| 46 | + guard let rawValue = TWCryptoBoxPublicKeyCreateWithData(dataData) else { | |
| 47 | + return nil | |
| 48 | + } | |
| 49 | + self.rawValue = rawValue | |
| 50 | + } | |
| 51 | + | |
| 52 | + deinit { | |
| 53 | + TWCryptoBoxPublicKeyDelete(rawValue) | |
| 54 | + } | |
| 55 | + | |
| 56 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/CryptoBoxSecretKey.swift
+68 −0
@@ -0,0 +1,68 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class CryptoBoxSecretKey { | |
| 14 | + | |
| 15 | + /// Determines if the given secret key is valid or not. | |
| 16 | + /// | |
| 17 | + /// - Parameter data: *non-null* byte array. | |
| 18 | + /// - Returns: true if the secret key is valid, false otherwise. | |
| 19 | + public static func isValid(data: Data) -> Bool { | |
| 20 | + let dataData = TWDataCreateWithNSData(data) | |
| 21 | + defer { | |
| 22 | + TWDataDelete(dataData) | |
| 23 | + } | |
| 24 | + return TWCryptoBoxSecretKeyIsValid(dataData) | |
| 25 | + } | |
| 26 | + | |
| 27 | + /// Returns the raw data of a given secret-key. | |
| 28 | + /// | |
| 29 | + /// - Parameter secret_key: *non-null* pointer to a secret key. | |
| 30 | + /// - Returns: C-compatible result with a C-compatible byte array. | |
| 31 | + public var data: Data { | |
| 32 | + return TWDataNSData(TWCryptoBoxSecretKeyData(rawValue)) | |
| 33 | + } | |
| 34 | + | |
| 35 | + let rawValue: OpaquePointer | |
| 36 | + | |
| 37 | + init(rawValue: OpaquePointer) { | |
| 38 | + self.rawValue = rawValue | |
| 39 | + } | |
| 40 | + | |
| 41 | + public init() { | |
| 42 | + rawValue = TWCryptoBoxSecretKeyCreate() | |
| 43 | + } | |
| 44 | + | |
| 45 | + public init?(data: Data) { | |
| 46 | + let dataData = TWDataCreateWithNSData(data) | |
| 47 | + defer { | |
| 48 | + TWDataDelete(dataData) | |
| 49 | + } | |
| 50 | + guard let rawValue = TWCryptoBoxSecretKeyCreateWithData(dataData) else { | |
| 51 | + return nil | |
| 52 | + } | |
| 53 | + self.rawValue = rawValue | |
| 54 | + } | |
| 55 | + | |
| 56 | + deinit { | |
| 57 | + TWCryptoBoxSecretKeyDelete(rawValue) | |
| 58 | + } | |
| 59 | + | |
| 60 | + /// Returns the public key associated with the given `key`. | |
| 61 | + /// | |
| 62 | + /// - Parameter key: *non-null* pointer to the private key. | |
| 63 | + /// - Returns: *non-null* pointer to the corresponding public key. | |
| 64 | + public func getPublicKey() -> CryptoBoxPublicKey { | |
| 65 | + return CryptoBoxPublicKey(rawValue: TWCryptoBoxSecretKeyGetPublicKey(rawValue)) | |
| 66 | + } | |
| 67 | + | |
| 68 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/DataVector.swift
+71 −0
@@ -0,0 +1,71 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// A vector of TWData byte arrays | |
| 13 | +public final class DataVector { | |
| 14 | + | |
| 15 | + /// Retrieve the number of elements | |
| 16 | + /// | |
| 17 | + /// - Parameter dataVector: A non-null Vector of data | |
| 18 | + /// - Returns: the size of the given vector. | |
| 19 | + public var size: Int { | |
| 20 | + return TWDataVectorSize(rawValue) | |
| 21 | + } | |
| 22 | + | |
| 23 | + let rawValue: OpaquePointer | |
| 24 | + | |
| 25 | + init(rawValue: OpaquePointer) { | |
| 26 | + self.rawValue = rawValue | |
| 27 | + } | |
| 28 | + | |
| 29 | + public init() { | |
| 30 | + rawValue = TWDataVectorCreate() | |
| 31 | + } | |
| 32 | + | |
| 33 | + public init(data: Data) { | |
| 34 | + let dataData = TWDataCreateWithNSData(data) | |
| 35 | + defer { | |
| 36 | + TWDataDelete(dataData) | |
| 37 | + } | |
| 38 | + rawValue = TWDataVectorCreateWithData(dataData) | |
| 39 | + } | |
| 40 | + | |
| 41 | + deinit { | |
| 42 | + TWDataVectorDelete(rawValue) | |
| 43 | + } | |
| 44 | + | |
| 45 | + /// Add an element to a Vector of Data. Element is cloned | |
| 46 | + /// | |
| 47 | + /// - Parameter dataVector: A non-null Vector of data | |
| 48 | + /// - Parameter data: A non-null valid block of data | |
| 49 | + /// - Note: data input parameter must be deleted on its own | |
| 50 | + public func add(data: Data) -> Void { | |
| 51 | + let dataData = TWDataCreateWithNSData(data) | |
| 52 | + defer { | |
| 53 | + TWDataDelete(dataData) | |
| 54 | + } | |
| 55 | + return TWDataVectorAdd(rawValue, dataData) | |
| 56 | + } | |
| 57 | + | |
| 58 | + /// Retrieve the n-th element. | |
| 59 | + /// | |
| 60 | + /// - Parameter dataVector: A non-null Vector of data | |
| 61 | + /// - Parameter index: index element of the vector to be retrieved, need to be < TWDataVectorSize | |
| 62 | + /// - Note: Returned element must be freed with \TWDataDelete | |
| 63 | + /// - Returns: A non-null block of data | |
| 64 | + public func get(index: Int) -> Data? { | |
| 65 | + guard let result = TWDataVectorGet(rawValue, index) else { | |
| 66 | + return nil | |
| 67 | + } | |
| 68 | + return TWDataNSData(result) | |
| 69 | + } | |
| 70 | + | |
| 71 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/DerivationPath.swift
+108 −0
@@ -0,0 +1,108 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a BIP44 DerivationPath in C++. | |
| 13 | +public final class DerivationPath { | |
| 14 | + | |
| 15 | + /// Returns the purpose enum of a DerivationPath. | |
| 16 | + /// | |
| 17 | + /// - Parameter path: DerivationPath to get the purpose of. | |
| 18 | + /// - Returns: DerivationPathPurpose. | |
| 19 | + public var purpose: Purpose { | |
| 20 | + return Purpose(rawValue: TWDerivationPathPurpose(rawValue).rawValue)! | |
| 21 | + } | |
| 22 | + | |
| 23 | + /// Returns the coin value of a derivation path. | |
| 24 | + /// | |
| 25 | + /// - Parameter path: DerivationPath to get the coin of. | |
| 26 | + /// - Returns: The coin part of the DerivationPath. | |
| 27 | + public var coin: UInt32 { | |
| 28 | + return TWDerivationPathCoin(rawValue) | |
| 29 | + } | |
| 30 | + | |
| 31 | + /// Returns the account value of a derivation path. | |
| 32 | + /// | |
| 33 | + /// - Parameter path: DerivationPath to get the account of. | |
| 34 | + /// - Returns: the account part of a derivation path. | |
| 35 | + public var account: UInt32 { | |
| 36 | + return TWDerivationPathAccount(rawValue) | |
| 37 | + } | |
| 38 | + | |
| 39 | + /// Returns the change value of a derivation path. | |
| 40 | + /// | |
| 41 | + /// - Parameter path: DerivationPath to get the change of. | |
| 42 | + /// - Returns: The change part of a derivation path. | |
| 43 | + public var change: UInt32 { | |
| 44 | + return TWDerivationPathChange(rawValue) | |
| 45 | + } | |
| 46 | + | |
| 47 | + /// Returns the address value of a derivation path. | |
| 48 | + /// | |
| 49 | + /// - Parameter path: DerivationPath to get the address of. | |
| 50 | + /// - Returns: The address part of the derivation path. | |
| 51 | + public var address: UInt32 { | |
| 52 | + return TWDerivationPathAddress(rawValue) | |
| 53 | + } | |
| 54 | + | |
| 55 | + /// Returns the string description of a derivation path. | |
| 56 | + /// | |
| 57 | + /// - Parameter path: DerivationPath to get the address of. | |
| 58 | + /// - Returns: The string description of the derivation path. | |
| 59 | + public var description: String { | |
| 60 | + return TWStringNSString(TWDerivationPathDescription(rawValue)) | |
| 61 | + } | |
| 62 | + | |
| 63 | + let rawValue: OpaquePointer | |
| 64 | + | |
| 65 | + init(rawValue: OpaquePointer) { | |
| 66 | + self.rawValue = rawValue | |
| 67 | + } | |
| 68 | + | |
| 69 | + public init(purpose: Purpose, coin: UInt32, account: UInt32, change: UInt32, address: UInt32) { | |
| 70 | + rawValue = TWDerivationPathCreate(TWPurpose(rawValue: purpose.rawValue), coin, account, change, address) | |
| 71 | + } | |
| 72 | + | |
| 73 | + public init?(string: String) { | |
| 74 | + let stringString = TWStringCreateWithNSString(string) | |
| 75 | + defer { | |
| 76 | + TWStringDelete(stringString) | |
| 77 | + } | |
| 78 | + guard let rawValue = TWDerivationPathCreateWithString(stringString) else { | |
| 79 | + return nil | |
| 80 | + } | |
| 81 | + self.rawValue = rawValue | |
| 82 | + } | |
| 83 | + | |
| 84 | + deinit { | |
| 85 | + TWDerivationPathDelete(rawValue) | |
| 86 | + } | |
| 87 | + | |
| 88 | + /// Returns the index component of a DerivationPath. | |
| 89 | + /// | |
| 90 | + /// - Parameter path: DerivationPath to get the index of. | |
| 91 | + /// - Parameter index: The index component of the DerivationPath. | |
| 92 | + /// - Returns: DerivationPathIndex or null if index is invalid. | |
| 93 | + public func indexAt(index: UInt32) -> DerivationPathIndex? { | |
| 94 | + guard let value = TWDerivationPathIndexAt(rawValue, index) else { | |
| 95 | + return nil | |
| 96 | + } | |
| 97 | + return DerivationPathIndex(rawValue: value) | |
| 98 | + } | |
| 99 | + | |
| 100 | + /// Returns the indices count of a DerivationPath. | |
| 101 | + /// | |
| 102 | + /// - Parameter path: DerivationPath to get the indices count of. | |
| 103 | + /// - Returns: The indices count of the DerivationPath. | |
| 104 | + public func indicesCount() -> UInt32 { | |
| 105 | + return TWDerivationPathIndicesCount(rawValue) | |
| 106 | + } | |
| 107 | + | |
| 108 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/DerivationPathIndex.swift
+52 −0
@@ -0,0 +1,52 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a derivation path index in C++ with value and hardened flag. | |
| 13 | +public final class DerivationPathIndex { | |
| 14 | + | |
| 15 | + /// Returns numeric value of an Index. | |
| 16 | + /// | |
| 17 | + /// - Parameter index: Index to get the numeric value of. | |
| 18 | + public var value: UInt32 { | |
| 19 | + return TWDerivationPathIndexValue(rawValue) | |
| 20 | + } | |
| 21 | + | |
| 22 | + /// Returns hardened flag of an Index. | |
| 23 | + /// | |
| 24 | + /// - Parameter index: Index to get hardened flag. | |
| 25 | + /// - Returns: true if hardened, false otherwise. | |
| 26 | + public var hardened: Bool { | |
| 27 | + return TWDerivationPathIndexHardened(rawValue) | |
| 28 | + } | |
| 29 | + | |
| 30 | + /// Returns the string description of a derivation path index. | |
| 31 | + /// | |
| 32 | + /// - Parameter path: Index to get the address of. | |
| 33 | + /// - Returns: The string description of the derivation path index. | |
| 34 | + public var description: String { | |
| 35 | + return TWStringNSString(TWDerivationPathIndexDescription(rawValue)) | |
| 36 | + } | |
| 37 | + | |
| 38 | + let rawValue: OpaquePointer | |
| 39 | + | |
| 40 | + init(rawValue: OpaquePointer) { | |
| 41 | + self.rawValue = rawValue | |
| 42 | + } | |
| 43 | + | |
| 44 | + public init(value: UInt32, hardened: Bool) { | |
| 45 | + rawValue = TWDerivationPathIndexCreate(value, hardened) | |
| 46 | + } | |
| 47 | + | |
| 48 | + deinit { | |
| 49 | + TWDerivationPathIndexDelete(rawValue) | |
| 50 | + } | |
| 51 | + | |
| 52 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Eip7702.swift
+78 −0
@@ -0,0 +1,78 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class Eip7702 { | |
| 14 | + | |
| 15 | + /// Signs an Authorization hash in [EIP-7702 format](https://eips.ethereum.org/EIPS/eip-7702) | |
| 16 | + /// | |
| 17 | + /// - Parameter chain_id: The chain ID of the user. | |
| 18 | + /// - Parameter contract_address: The address of the smart contract wallet. | |
| 19 | + /// - Parameter nonce: The nonce of the user. | |
| 20 | + /// - Parameter private_key: The private key of the user. | |
| 21 | + /// - Returns: The signed authorization. | |
| 22 | + public static func signAuthorization(chainId: Data, contractAddress: String, nonce: Data, privateKey: String) -> String? { | |
| 23 | + let chainIdData = TWDataCreateWithNSData(chainId) | |
| 24 | + defer { | |
| 25 | + TWDataDelete(chainIdData) | |
| 26 | + } | |
| 27 | + let contractAddressString = TWStringCreateWithNSString(contractAddress) | |
| 28 | + defer { | |
| 29 | + TWStringDelete(contractAddressString) | |
| 30 | + } | |
| 31 | + let nonceData = TWDataCreateWithNSData(nonce) | |
| 32 | + defer { | |
| 33 | + TWDataDelete(nonceData) | |
| 34 | + } | |
| 35 | + let privateKeyString = TWStringCreateWithNSString(privateKey) | |
| 36 | + defer { | |
| 37 | + TWStringDelete(privateKeyString) | |
| 38 | + } | |
| 39 | + guard let result = TWEip7702SignAuthorization(chainIdData, contractAddressString, nonceData, privateKeyString) else { | |
| 40 | + return nil | |
| 41 | + } | |
| 42 | + return TWStringNSString(result) | |
| 43 | + } | |
| 44 | + | |
| 45 | + /// Computes an Authorization hash in [EIP-7702 format](https://eips.ethereum.org/EIPS/eip-7702) | |
| 46 | + /// `keccak256('0x05' || rlp([chain_id, address, nonce]))`. | |
| 47 | + /// | |
| 48 | + /// - Parameter chain_id: The chain ID of the user. | |
| 49 | + /// - Parameter contract_address: The address of the smart contract wallet. | |
| 50 | + /// - Parameter nonce: The nonce of the user. | |
| 51 | + /// - Returns: The authorization hash. | |
| 52 | + public static func getAuthorizationHash(chainId: Data, contractAddress: String, nonce: Data) -> Data? { | |
| 53 | + let chainIdData = TWDataCreateWithNSData(chainId) | |
| 54 | + defer { | |
| 55 | + TWDataDelete(chainIdData) | |
| 56 | + } | |
| 57 | + let contractAddressString = TWStringCreateWithNSString(contractAddress) | |
| 58 | + defer { | |
| 59 | + TWStringDelete(contractAddressString) | |
| 60 | + } | |
| 61 | + let nonceData = TWDataCreateWithNSData(nonce) | |
| 62 | + defer { | |
| 63 | + TWDataDelete(nonceData) | |
| 64 | + } | |
| 65 | + guard let result = TWEip7702GetAuthorizationHash(chainIdData, contractAddressString, nonceData) else { | |
| 66 | + return nil | |
| 67 | + } | |
| 68 | + return TWDataNSData(result) | |
| 69 | + } | |
| 70 | + | |
| 71 | + let rawValue: OpaquePointer | |
| 72 | + | |
| 73 | + init(rawValue: OpaquePointer) { | |
| 74 | + self.rawValue = rawValue | |
| 75 | + } | |
| 76 | + | |
| 77 | + | |
| 78 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/AESPaddingMode.swift
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Padding mode used in AES encryption. | |
| 11 | +public enum AESPaddingMode: UInt32, CaseIterable { | |
| 12 | + case zero = 0 | |
| 13 | + case pkcs7 = 1 | |
| 14 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/BitcoinSigHashType.swift
+17 −0
@@ -0,0 +1,17 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Bitcoin SIGHASH type. | |
| 11 | +public enum BitcoinSigHashType: UInt32, CaseIterable { | |
| 12 | + case all = 0x01 | |
| 13 | + case none = 0x02 | |
| 14 | + case single = 0x03 | |
| 15 | + case fork = 0x40 | |
| 16 | + case forkBTG = 0x4f40 | |
| 17 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/Blockchain.swift
+70 −0
@@ -0,0 +1,70 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Blockchain enum type | |
| 11 | +public enum Blockchain: UInt32, CaseIterable { | |
| 12 | + case bitcoin = 0 | |
| 13 | + case ethereum = 1 | |
| 14 | + case vechain = 3 | |
| 15 | + case tron = 4 | |
| 16 | + case icon = 5 | |
| 17 | + case binance = 6 | |
| 18 | + case ripple = 7 | |
| 19 | + case tezos = 8 | |
| 20 | + case nimiq = 9 | |
| 21 | + case stellar = 10 | |
| 22 | + case aion = 11 | |
| 23 | + case cosmos = 12 | |
| 24 | + case theta = 13 | |
| 25 | + case ontology = 14 | |
| 26 | + case zilliqa = 15 | |
| 27 | + case ioTeX = 16 | |
| 28 | + case eos = 17 | |
| 29 | + case nano = 18 | |
| 30 | + case nuls = 19 | |
| 31 | + case waves = 20 | |
| 32 | + case aeternity = 21 | |
| 33 | + case nebulas = 22 | |
| 34 | + case fio = 23 | |
| 35 | + case solana = 24 | |
| 36 | + case harmony = 25 | |
| 37 | + case near = 26 | |
| 38 | + case algorand = 27 | |
| 39 | + case iost = 28 | |
| 40 | + case polkadot = 29 | |
| 41 | + case cardano = 30 | |
| 42 | + case neo = 31 | |
| 43 | + case filecoin = 32 | |
| 44 | + case multiversX = 33 | |
| 45 | + case oasisNetwork = 34 | |
| 46 | + case decred = 35 | |
| 47 | + case zcash = 36 | |
| 48 | + case groestlcoin = 37 | |
| 49 | + case thorchain = 38 | |
| 50 | + case ronin = 39 | |
| 51 | + case kusama = 40 | |
| 52 | + case zen = 41 | |
| 53 | + case bitcoinDiamond = 42 | |
| 54 | + case verge = 43 | |
| 55 | + case nervos = 44 | |
| 56 | + case everscale = 45 | |
| 57 | + case aptos = 46 | |
| 58 | + case nebl = 47 | |
| 59 | + case hedera = 48 | |
| 60 | + case theOpenNetwork = 49 | |
| 61 | + case sui = 50 | |
| 62 | + case greenfield = 51 | |
| 63 | + case internetComputer = 52 | |
| 64 | + case nativeEvmos = 53 | |
| 65 | + case nativeInjective = 54 | |
| 66 | + case bitcoinCash = 55 | |
| 67 | + case pactus = 56 | |
| 68 | + case komodo = 57 | |
| 69 | + case polymesh = 58 | |
| 70 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/CoinType.swift
+181 −0
@@ -0,0 +1,181 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Represents a private key./// Represents a public key./// Coin type for Level 2 of BIP44. | |
| 11 | +/// | |
| 12 | +/// \see https://github.com/satoshilabs/slips/blob/master/slip-0044.md | |
| 13 | +public enum CoinType: UInt32, CaseIterable { | |
| 14 | + case aeternity = 457 | |
| 15 | + case aion = 425 | |
| 16 | + case binance = 714 | |
| 17 | + case bitcoin = 0 | |
| 18 | + case bitcoinCash = 145 | |
| 19 | + case bitcoinGold = 156 | |
| 20 | + case callisto = 820 | |
| 21 | + case cardano = 1815 | |
| 22 | + case cosmos = 118 | |
| 23 | + case pivx = 119 | |
| 24 | + case dash = 5 | |
| 25 | + case decred = 42 | |
| 26 | + case digiByte = 20 | |
| 27 | + case dogecoin = 3 | |
| 28 | + case eos = 194 | |
| 29 | + case wax = 14001 | |
| 30 | + case ethereum = 60 | |
| 31 | + case ethereumClassic = 61 | |
| 32 | + case fio = 235 | |
| 33 | + case goChain = 6060 | |
| 34 | + case groestlcoin = 17 | |
| 35 | + case icon = 74 | |
| 36 | + case ioTeX = 304 | |
| 37 | + case kava = 459 | |
| 38 | + case kin = 2017 | |
| 39 | + case litecoin = 2 | |
| 40 | + case monacoin = 22 | |
| 41 | + case nebulas = 2718 | |
| 42 | + case nuls = 8964 | |
| 43 | + case nano = 165 | |
| 44 | + case near = 397 | |
| 45 | + case nimiq = 242 | |
| 46 | + case ontology = 1024 | |
| 47 | + case poanetwork = 178 | |
| 48 | + case qtum = 2301 | |
| 49 | + case xrp = 144 | |
| 50 | + case solana = 501 | |
| 51 | + case stellar = 148 | |
| 52 | + case tezos = 1729 | |
| 53 | + case theta = 500 | |
| 54 | + case thunderCore = 1001 | |
| 55 | + case neo = 888 | |
| 56 | + case viction = 889 | |
| 57 | + case tron = 195 | |
| 58 | + case veChain = 818 | |
| 59 | + case viacoin = 14 | |
| 60 | + case wanchain = 5718350 | |
| 61 | + case zcash = 133 | |
| 62 | + case firo = 136 | |
| 63 | + case zilliqa = 313 | |
| 64 | + case zelcash = 19167 | |
| 65 | + case ravencoin = 175 | |
| 66 | + case waves = 5741564 | |
| 67 | + case terra = 330 | |
| 68 | + case terraV2 = 10000330 | |
| 69 | + case harmony = 1023 | |
| 70 | + case algorand = 283 | |
| 71 | + case kusama = 434 | |
| 72 | + case polkadot = 354 | |
| 73 | + case filecoin = 461 | |
| 74 | + case multiversX = 508 | |
| 75 | + case bandChain = 494 | |
| 76 | + case smartChainLegacy = 10000714 | |
| 77 | + case smartChain = 20000714 | |
| 78 | + case tbinance = 30000714 | |
| 79 | + case oasis = 474 | |
| 80 | + case polygon = 966 | |
| 81 | + case thorchain = 931 | |
| 82 | + case bluzelle = 483 | |
| 83 | + case optimism = 10000070 | |
| 84 | + case zksync = 10000324 | |
| 85 | + case arbitrum = 10042221 | |
| 86 | + case ecochain = 10000553 | |
| 87 | + case avalancheCChain = 10009000 | |
| 88 | + case xdai = 10000100 | |
| 89 | + case fantom = 10000250 | |
| 90 | + case cryptoOrg = 394 | |
| 91 | + case celo = 52752 | |
| 92 | + case ronin = 10002020 | |
| 93 | + case osmosis = 10000118 | |
| 94 | + case ecash = 899 | |
| 95 | + case iost = 291 | |
| 96 | + case cronosChain = 10000025 | |
| 97 | + case smartBitcoinCash = 10000145 | |
| 98 | + case kuCoinCommunityChain = 10000321 | |
| 99 | + case bitcoinDiamond = 999 | |
| 100 | + case boba = 10000288 | |
| 101 | + case syscoin = 57 | |
| 102 | + case verge = 77 | |
| 103 | + case zen = 121 | |
| 104 | + case metis = 10001088 | |
| 105 | + case aurora = 1323161554 | |
| 106 | + case evmos = 10009001 | |
| 107 | + case nativeEvmos = 20009001 | |
| 108 | + case moonriver = 10001285 | |
| 109 | + case moonbeam = 10001284 | |
| 110 | + case kavaEvm = 10002222 | |
| 111 | + case kaia = 10008217 | |
| 112 | + case meter = 18000 | |
| 113 | + case okxchain = 996 | |
| 114 | + case stratis = 105105 | |
| 115 | + case komodo = 141 | |
| 116 | + case nervos = 309 | |
| 117 | + case everscale = 396 | |
| 118 | + case aptos = 637 | |
| 119 | + case nebl = 146 | |
| 120 | + case hedera = 3030 | |
| 121 | + case secret = 529 | |
| 122 | + case nativeInjective = 10000060 | |
| 123 | + case agoric = 564 | |
| 124 | + case ton = 607 | |
| 125 | + case sui = 784 | |
| 126 | + case stargaze = 20000118 | |
| 127 | + case polygonzkEVM = 10001101 | |
| 128 | + case juno = 30000118 | |
| 129 | + case stride = 40000118 | |
| 130 | + case axelar = 50000118 | |
| 131 | + case crescent = 60000118 | |
| 132 | + case kujira = 70000118 | |
| 133 | + case ioTeXEVM = 10004689 | |
| 134 | + case nativeCanto = 10007700 | |
| 135 | + case comdex = 80000118 | |
| 136 | + case neutron = 90000118 | |
| 137 | + case sommelier = 11000118 | |
| 138 | + case fetchAI = 12000118 | |
| 139 | + case mars = 13000118 | |
| 140 | + case umee = 14000118 | |
| 141 | + case coreum = 10000990 | |
| 142 | + case quasar = 15000118 | |
| 143 | + case persistence = 16000118 | |
| 144 | + case akash = 17000118 | |
| 145 | + case noble = 18000118 | |
| 146 | + case scroll = 534352 | |
| 147 | + case rootstock = 137 | |
| 148 | + case thetaFuel = 361 | |
| 149 | + case confluxeSpace = 1030 | |
| 150 | + case acala = 787 | |
| 151 | + case acalaEVM = 10000787 | |
| 152 | + case opBNB = 204 | |
| 153 | + case neon = 245022934 | |
| 154 | + case base = 8453 | |
| 155 | + case sei = 19000118 | |
| 156 | + case arbitrumNova = 10042170 | |
| 157 | + case linea = 59144 | |
| 158 | + case greenfield = 5600 | |
| 159 | + case mantle = 5000 | |
| 160 | + case zenEON = 7332 | |
| 161 | + case internetComputer = 223 | |
| 162 | + case tia = 21000118 | |
| 163 | + case mantaPacific = 169 | |
| 164 | + case nativeZetaChain = 10007000 | |
| 165 | + case zetaEVM = 20007000 | |
| 166 | + case dydx = 22000118 | |
| 167 | + case merlin = 4200 | |
| 168 | + case lightlink = 1890 | |
| 169 | + case blast = 81457 | |
| 170 | + case bounceBit = 6001 | |
| 171 | + case zkLinkNova = 810180 | |
| 172 | + case pactus = 21888 | |
| 173 | + case sonic = 10000146 | |
| 174 | + case polymesh = 595 | |
| 175 | + case plasma = 9745 | |
| 176 | + case monad = 10143 | |
| 177 | + case megaETH = 4326 | |
| 178 | + case seiEVM = 1329 | |
| 179 | + case hyperEVM = 10000999 | |
| 180 | + case robinhoodChain = 10004663 | |
| 181 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/Curve.swift
+31 −0
@@ -0,0 +1,31 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Elliptic cruves | |
| 11 | +public enum Curve: UInt32, CaseIterable, CustomStringConvertible { | |
| 12 | + case secp256k1 = 0 | |
| 13 | + case ed25519 = 1 | |
| 14 | + case ed25519Blake2bNano = 2 | |
| 15 | + case curve25519 = 3 | |
| 16 | + case nist256p1 = 4 | |
| 17 | + case ed25519ExtendedCardano = 5 | |
| 18 | + case starkex = 6 | |
| 19 | + | |
| 20 | + public var description: String { | |
| 21 | + switch self { | |
| 22 | + case .secp256k1: return "secp256k1" | |
| 23 | + case .ed25519: return "ed25519" | |
| 24 | + case .ed25519Blake2bNano: return "ed25519-blake2b-nano" | |
| 25 | + case .curve25519: return "curve25519" | |
| 26 | + case .nist256p1: return "nist256p1" | |
| 27 | + case .ed25519ExtendedCardano: return "ed25519-cardano-seed" | |
| 28 | + case .starkex: return "starkex" | |
| 29 | + } | |
| 30 | + } | |
| 31 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/Derivation.swift
+26 −0
@@ -0,0 +1,26 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Non-default coin address derivation names (default, unnamed derivations are not included). | |
| 11 | +/// Note the enum variant must be sync with `TWDerivation` enum in Rust: | |
| 12 | +/// https://github.com/trustwallet/wallet-core/blob/master/rust/tw_coin_registry/src/tw_derivation.rs | |
| 13 | +public enum Derivation: UInt32, CaseIterable { | |
| 14 | + case `default` = 0 | |
| 15 | + case custom = 1 | |
| 16 | + case bitcoinSegwit = 2 | |
| 17 | + case bitcoinLegacy = 3 | |
| 18 | + case bitcoinTestnet = 4 | |
| 19 | + case litecoinLegacy = 5 | |
| 20 | + case solanaSolana = 6 | |
| 21 | + case stratisSegwit = 7 | |
| 22 | + case bitcoinTaproot = 8 | |
| 23 | + case pactusMainnet = 9 | |
| 24 | + case pactusTestnet = 10 | |
| 25 | + case smartChainStableAccount = 11 | |
| 26 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/EthereumChainID.swift
+74 −0
@@ -0,0 +1,74 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Chain identifiers for Ethereum-based blockchains, for convenience. Recommended to use the dynamic CoinType.ChainId() instead. | |
| 11 | +/// See also TWChainId. | |
| 12 | +public enum EthereumChainID: UInt32, CaseIterable { | |
| 13 | + case ethereum = 1 | |
| 14 | + case classic = 61 | |
| 15 | + case rootstock = 30 | |
| 16 | + case manta = 169 | |
| 17 | + case poa = 99 | |
| 18 | + case opbnb = 204 | |
| 19 | + case tfuelevm = 361 | |
| 20 | + case vechain = 74 | |
| 21 | + case callisto = 820 | |
| 22 | + case viction = 88 | |
| 23 | + case polygon = 137 | |
| 24 | + case okc = 66 | |
| 25 | + case thundertoken = 108 | |
| 26 | + case cfxevm = 1030 | |
| 27 | + case seievm = 1329 | |
| 28 | + case lightlink = 1890 | |
| 29 | + case merlin = 4200 | |
| 30 | + case megaeth = 4326 | |
| 31 | + case mantle = 5000 | |
| 32 | + case bouncebit = 6001 | |
| 33 | + case gochain = 60 | |
| 34 | + case zeneon = 7332 | |
| 35 | + case base = 8453 | |
| 36 | + case plasma = 9745 | |
| 37 | + case monad = 143 | |
| 38 | + case meter = 82 | |
| 39 | + case celo = 42220 | |
| 40 | + case linea = 59144 | |
| 41 | + case blast = 81457 | |
| 42 | + case scroll = 534352 | |
| 43 | + case zklinknova = 810180 | |
| 44 | + case wanchain = 888 | |
| 45 | + case cronos = 25 | |
| 46 | + case optimism = 10 | |
| 47 | + case xdai = 100 | |
| 48 | + case smartbch = 10000 | |
| 49 | + case sonic = 146 | |
| 50 | + case fantom = 250 | |
| 51 | + case boba = 288 | |
| 52 | + case kcc = 321 | |
| 53 | + case zksync = 324 | |
| 54 | + case heco = 128 | |
| 55 | + case acalaevm = 787 | |
| 56 | + case hyperevm = 999 | |
| 57 | + case metis = 1088 | |
| 58 | + case polygonzkevm = 1101 | |
| 59 | + case moonbeam = 1284 | |
| 60 | + case moonriver = 1285 | |
| 61 | + case ronin = 2020 | |
| 62 | + case kavaevm = 2222 | |
| 63 | + case robinhoodchain = 4663 | |
| 64 | + case iotexevm = 4689 | |
| 65 | + case kaia = 8217 | |
| 66 | + case avalanchec = 43114 | |
| 67 | + case evmos = 9001 | |
| 68 | + case arbitrumnova = 42170 | |
| 69 | + case arbitrum = 42161 | |
| 70 | + case smartchain = 56 | |
| 71 | + case zetaevm = 7000 | |
| 72 | + case neon = 245022934 | |
| 73 | + case aurora = 1313161554 | |
| 74 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/FilecoinAddressType.swift
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Filecoin address type. | |
| 11 | +public enum FilecoinAddressType: UInt32, CaseIterable { | |
| 12 | + case `default` = 0 | |
| 13 | + case delegated = 1 | |
| 14 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/FiroAddressType.swift
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Firo address type. | |
| 11 | +public enum FiroAddressType: UInt32, CaseIterable { | |
| 12 | + case `default` = 0 | |
| 13 | + case exchange = 1 | |
| 14 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/HDVersion.swift
+35 −0
@@ -0,0 +1,35 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Registered HD version bytes | |
| 11 | +/// | |
| 12 | +/// \see https://github.com/satoshilabs/slips/blob/master/slip-0132.md | |
| 13 | +public enum HDVersion: UInt32, CaseIterable { | |
| 14 | + case none = 0 | |
| 15 | + case xpub = 0x0488b21e | |
| 16 | + case xprv = 0x0488ade4 | |
| 17 | + case ypub = 0x049d7cb2 | |
| 18 | + case yprv = 0x049d7878 | |
| 19 | + case zpub = 0x04b24746 | |
| 20 | + case zprv = 0x04b2430c | |
| 21 | + case vpub = 0x045f1cf6 | |
| 22 | + case vprv = 0x045f18bc | |
| 23 | + case tpub = 0x043587cf | |
| 24 | + case tprv = 0x04358394 | |
| 25 | + case ltub = 0x019da462 | |
| 26 | + case ltpv = 0x019d9cfe | |
| 27 | + case mtub = 0x01b26ef6 | |
| 28 | + case mtpv = 0x01b26792 | |
| 29 | + case ttub = 0x0436f6e1 | |
| 30 | + case ttpv = 0x0436ef7d | |
| 31 | + case dpub = 0x2fda926 | |
| 32 | + case dprv = 0x2fda4e8 | |
| 33 | + case dgub = 0x02facafd | |
| 34 | + case dgpv = 0x02fac398 | |
| 35 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/HRP.swift
+141 −0
@@ -0,0 +1,141 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Registered human-readable parts for BIP-0173 | |
| 11 | +/// | |
| 12 | +/// - SeeAlso: https://github.com/satoshilabs/slips/blob/master/slip-0173.md | |
| 13 | +public enum HRP: UInt32, CaseIterable, CustomStringConvertible { | |
| 14 | + case unknown = 0 | |
| 15 | + case bitcoin = 1 | |
| 16 | + case litecoin = 2 | |
| 17 | + case viacoin = 3 | |
| 18 | + case groestlcoin = 4 | |
| 19 | + case digiByte = 5 | |
| 20 | + case monacoin = 6 | |
| 21 | + case syscoin = 7 | |
| 22 | + case verge = 8 | |
| 23 | + case cosmos = 9 | |
| 24 | + case zcash = 10 | |
| 25 | + case bitcoinCash = 11 | |
| 26 | + case bitcoinGold = 12 | |
| 27 | + case ioTeX = 13 | |
| 28 | + case nervos = 14 | |
| 29 | + case zilliqa = 15 | |
| 30 | + case terra = 16 | |
| 31 | + case cryptoOrg = 17 | |
| 32 | + case kava = 18 | |
| 33 | + case oasis = 19 | |
| 34 | + case bluzelle = 20 | |
| 35 | + case bandChain = 21 | |
| 36 | + case multiversX = 22 | |
| 37 | + case secret = 23 | |
| 38 | + case agoric = 24 | |
| 39 | + case binance = 25 | |
| 40 | + case ecash = 26 | |
| 41 | + case thorchain = 27 | |
| 42 | + case bitcoinDiamond = 28 | |
| 43 | + case harmony = 29 | |
| 44 | + case cardano = 30 | |
| 45 | + case qtum = 31 | |
| 46 | + case pactus = 32 | |
| 47 | + case stratis = 33 | |
| 48 | + case nativeInjective = 34 | |
| 49 | + case osmosis = 35 | |
| 50 | + case terraV2 = 36 | |
| 51 | + case coreum = 37 | |
| 52 | + case nativeZetaChain = 38 | |
| 53 | + case nativeCanto = 39 | |
| 54 | + case sommelier = 40 | |
| 55 | + case fetchAI = 41 | |
| 56 | + case mars = 42 | |
| 57 | + case umee = 43 | |
| 58 | + case quasar = 44 | |
| 59 | + case persistence = 45 | |
| 60 | + case akash = 46 | |
| 61 | + case noble = 47 | |
| 62 | + case sei = 48 | |
| 63 | + case stargaze = 49 | |
| 64 | + case nativeEvmos = 50 | |
| 65 | + case tia = 51 | |
| 66 | + case dydx = 52 | |
| 67 | + case juno = 53 | |
| 68 | + case tbinance = 54 | |
| 69 | + case stride = 55 | |
| 70 | + case axelar = 56 | |
| 71 | + case crescent = 57 | |
| 72 | + case kujira = 58 | |
| 73 | + case comdex = 59 | |
| 74 | + case neutron = 60 | |
| 75 | + | |
| 76 | + public var description: String { | |
| 77 | + switch self { | |
| 78 | + case .unknown: return "" | |
| 79 | + case .bitcoin: return "bc" | |
| 80 | + case .litecoin: return "ltc" | |
| 81 | + case .viacoin: return "via" | |
| 82 | + case .groestlcoin: return "grs" | |
| 83 | + case .digiByte: return "dgb" | |
| 84 | + case .monacoin: return "mona" | |
| 85 | + case .syscoin: return "sys" | |
| 86 | + case .verge: return "vg" | |
| 87 | + case .cosmos: return "cosmos" | |
| 88 | + case .zcash: return "tex" | |
| 89 | + case .bitcoinCash: return "bitcoincash" | |
| 90 | + case .bitcoinGold: return "btg" | |
| 91 | + case .ioTeX: return "io" | |
| 92 | + case .nervos: return "ckb" | |
| 93 | + case .zilliqa: return "zil" | |
| 94 | + case .terra: return "terra" | |
| 95 | + case .cryptoOrg: return "cro" | |
| 96 | + case .kava: return "kava" | |
| 97 | + case .oasis: return "oasis" | |
| 98 | + case .bluzelle: return "bluzelle" | |
| 99 | + case .bandChain: return "band" | |
| 100 | + case .multiversX: return "erd" | |
| 101 | + case .secret: return "secret" | |
| 102 | + case .agoric: return "agoric" | |
| 103 | + case .binance: return "bnb" | |
| 104 | + case .ecash: return "ecash" | |
| 105 | + case .thorchain: return "thor" | |
| 106 | + case .bitcoinDiamond: return "bcd" | |
| 107 | + case .harmony: return "one" | |
| 108 | + case .cardano: return "addr" | |
| 109 | + case .qtum: return "qc" | |
| 110 | + case .pactus: return "pc" | |
| 111 | + case .stratis: return "strax" | |
| 112 | + case .nativeInjective: return "inj" | |
| 113 | + case .osmosis: return "osmo" | |
| 114 | + case .terraV2: return "terra" | |
| 115 | + case .coreum: return "core" | |
| 116 | + case .nativeZetaChain: return "zeta" | |
| 117 | + case .nativeCanto: return "canto" | |
| 118 | + case .sommelier: return "somm" | |
| 119 | + case .fetchAI: return "fetch" | |
| 120 | + case .mars: return "mars" | |
| 121 | + case .umee: return "umee" | |
| 122 | + case .quasar: return "quasar" | |
| 123 | + case .persistence: return "persistence" | |
| 124 | + case .akash: return "akash" | |
| 125 | + case .noble: return "noble" | |
| 126 | + case .sei: return "sei" | |
| 127 | + case .stargaze: return "stars" | |
| 128 | + case .nativeEvmos: return "evmos" | |
| 129 | + case .tia: return "celestia" | |
| 130 | + case .dydx: return "dydx" | |
| 131 | + case .juno: return "juno" | |
| 132 | + case .tbinance: return "tbnb" | |
| 133 | + case .stride: return "stride" | |
| 134 | + case .axelar: return "axelar" | |
| 135 | + case .crescent: return "cre" | |
| 136 | + case .kujira: return "kujira" | |
| 137 | + case .comdex: return "comdex" | |
| 138 | + case .neutron: return "neutron" | |
| 139 | + } | |
| 140 | + } | |
| 141 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/PrivateKeyType.swift
+14 −0
@@ -0,0 +1,14 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Private key types, the vast majority of chains use the default, 32-byte key. | |
| 11 | +public enum PrivateKeyType: UInt32, CaseIterable { | |
| 12 | + case `default` = 0 | |
| 13 | + case cardano = 1 | |
| 14 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/PublicKeyType.swift
+21 −0
@@ -0,0 +1,21 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Public key types | |
| 11 | +public enum PublicKeyType: UInt32, CaseIterable { | |
| 12 | + case secp256k1 = 0 | |
| 13 | + case secp256k1Extended = 1 | |
| 14 | + case nist256p1 = 2 | |
| 15 | + case nist256p1Extended = 3 | |
| 16 | + case ed25519 = 4 | |
| 17 | + case ed25519Blake2b = 5 | |
| 18 | + case curve25519 = 6 | |
| 19 | + case ed25519Cardano = 7 | |
| 20 | + case starkex = 8 | |
| 21 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/Purpose.swift
+21 −0
@@ -0,0 +1,21 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// HD wallet purpose | |
| 11 | +/// | |
| 12 | +/// \see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki | |
| 13 | +/// \see https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki | |
| 14 | +/// \see https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki | |
| 15 | +public enum Purpose: UInt32, CaseIterable { | |
| 16 | + case bip44 = 44 | |
| 17 | + case bip49 = 49 | |
| 18 | + case bip84 = 84 | |
| 19 | + case bip86 = 86 | |
| 20 | + case bip1852 = 1852 | |
| 21 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/StellarMemoType.swift
+17 −0
@@ -0,0 +1,17 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Stellar memo type. | |
| 11 | +public enum StellarMemoType: UInt32, CaseIterable { | |
| 12 | + case none = 0 | |
| 13 | + case text = 1 | |
| 14 | + case id = 2 | |
| 15 | + case hash = 3 | |
| 16 | + case `return` = 4 | |
| 17 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/StellarPassphrase.swift
+21 −0
@@ -0,0 +1,21 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Stellar network passphrase string. | |
| 11 | +public enum StellarPassphrase: UInt32, CaseIterable, CustomStringConvertible { | |
| 12 | + case stellar = 0 | |
| 13 | + case kin = 1 | |
| 14 | + | |
| 15 | + public var description: String { | |
| 16 | + switch self { | |
| 17 | + case .stellar: return "Public Global Stellar Network ; September 2015" | |
| 18 | + case .kin: return "Kin Mainnet ; December 2018" | |
| 19 | + } | |
| 20 | + } | |
| 21 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/StellarVersionByte.swift
+16 −0
@@ -0,0 +1,16 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Stellar address version byte. | |
| 11 | +public enum StellarVersionByte: UInt16, CaseIterable { | |
| 12 | + case accountID = 0x30 | |
| 13 | + case seed = 0xc0 | |
| 14 | + case preAuthTX = 0xc8 | |
| 15 | + case sha256Hash = 0x118 | |
| 16 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/StoredKeyEncryption.swift
+15 −0
@@ -0,0 +1,15 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Preset encryption kind | |
| 11 | +public enum StoredKeyEncryption: UInt32, CaseIterable { | |
| 12 | + case aes128Ctr = 0 | |
| 13 | + case aes192Ctr = 2 | |
| 14 | + case aes256Ctr = 3 | |
| 15 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Enums/StoredKeyEncryptionLevel.swift
+16 −0
@@ -0,0 +1,16 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +/// Preset encryption parameter with different security strength, for key store | |
| 11 | +public enum StoredKeyEncryptionLevel: UInt32, CaseIterable { | |
| 12 | + case `default` = 0 | |
| 13 | + case minimal = 1 | |
| 14 | + case weak = 2 | |
| 15 | + case standard = 3 | |
| 16 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Ethereum.swift
+112 −0
@@ -0,0 +1,112 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class Ethereum { | |
| 14 | + | |
| 15 | + /// Returns the checksummed address. | |
| 16 | + /// | |
| 17 | + /// - Parameter address: *non-null* string. | |
| 18 | + /// - Returns: the checksummed address. | |
| 19 | + public static func addressChecksummed(address: String) -> String? { | |
| 20 | + let addressString = TWStringCreateWithNSString(address) | |
| 21 | + defer { | |
| 22 | + TWStringDelete(addressString) | |
| 23 | + } | |
| 24 | + guard let result = TWEthereumAddressChecksummed(addressString) else { | |
| 25 | + return nil | |
| 26 | + } | |
| 27 | + return TWStringNSString(result) | |
| 28 | + } | |
| 29 | + | |
| 30 | + /// Returns the account path from address. | |
| 31 | + /// | |
| 32 | + /// - Parameter eth_address: *non-null* string. | |
| 33 | + /// - Parameter layer: *non-null* string. | |
| 34 | + /// - Parameter application: *non-null* string. | |
| 35 | + /// - Parameter index: *non-null* string. | |
| 36 | + /// - Returns: the account path. | |
| 37 | + public static func eip2645GetPath(ethAddress: String, layer: String, application: String, index: String) -> String? { | |
| 38 | + let ethAddressString = TWStringCreateWithNSString(ethAddress) | |
| 39 | + defer { | |
| 40 | + TWStringDelete(ethAddressString) | |
| 41 | + } | |
| 42 | + let layerString = TWStringCreateWithNSString(layer) | |
| 43 | + defer { | |
| 44 | + TWStringDelete(layerString) | |
| 45 | + } | |
| 46 | + let applicationString = TWStringCreateWithNSString(application) | |
| 47 | + defer { | |
| 48 | + TWStringDelete(applicationString) | |
| 49 | + } | |
| 50 | + let indexString = TWStringCreateWithNSString(index) | |
| 51 | + defer { | |
| 52 | + TWStringDelete(indexString) | |
| 53 | + } | |
| 54 | + guard let result = TWEthereumEip2645GetPath(ethAddressString, layerString, applicationString, indexString) else { | |
| 55 | + return nil | |
| 56 | + } | |
| 57 | + return TWStringNSString(result) | |
| 58 | + } | |
| 59 | + | |
| 60 | + /// Returns EIP-1014 Create2 address | |
| 61 | + /// | |
| 62 | + /// - Parameter from: *non-null* string. | |
| 63 | + /// - Parameter salt: *non-null* data. | |
| 64 | + /// - Parameter init_code_hash: *non-null* data. | |
| 65 | + /// - Returns: the EIP-1014 Create2 address. | |
| 66 | + public static func eip1014Create2Address(from: String, salt: Data, initCodeHash: Data) -> String? { | |
| 67 | + let fromString = TWStringCreateWithNSString(from) | |
| 68 | + defer { | |
| 69 | + TWStringDelete(fromString) | |
| 70 | + } | |
| 71 | + let saltData = TWDataCreateWithNSData(salt) | |
| 72 | + defer { | |
| 73 | + TWDataDelete(saltData) | |
| 74 | + } | |
| 75 | + let initCodeHashData = TWDataCreateWithNSData(initCodeHash) | |
| 76 | + defer { | |
| 77 | + TWDataDelete(initCodeHashData) | |
| 78 | + } | |
| 79 | + guard let result = TWEthereumEip1014Create2Address(fromString, saltData, initCodeHashData) else { | |
| 80 | + return nil | |
| 81 | + } | |
| 82 | + return TWStringNSString(result) | |
| 83 | + } | |
| 84 | + | |
| 85 | + /// Returns EIP-1967 proxy init code | |
| 86 | + /// | |
| 87 | + /// - Parameter logic_address: *non-null* string. | |
| 88 | + /// - Parameter data: *non-null* data. | |
| 89 | + /// - Returns: the EIP-1967 proxy init code. | |
| 90 | + public static func eip1967ProxyInitCode(logicAddress: String, data: Data) -> Data? { | |
| 91 | + let logicAddressString = TWStringCreateWithNSString(logicAddress) | |
| 92 | + defer { | |
| 93 | + TWStringDelete(logicAddressString) | |
| 94 | + } | |
| 95 | + let dataData = TWDataCreateWithNSData(data) | |
| 96 | + defer { | |
| 97 | + TWDataDelete(dataData) | |
| 98 | + } | |
| 99 | + guard let result = TWEthereumEip1967ProxyInitCode(logicAddressString, dataData) else { | |
| 100 | + return nil | |
| 101 | + } | |
| 102 | + return TWDataNSData(result) | |
| 103 | + } | |
| 104 | + | |
| 105 | + let rawValue: OpaquePointer | |
| 106 | + | |
| 107 | + init(rawValue: OpaquePointer) { | |
| 108 | + self.rawValue = rawValue | |
| 109 | + } | |
| 110 | + | |
| 111 | + | |
| 112 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/EthereumAbi.swift
+174 −0
@@ -0,0 +1,174 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Wrapper class for Ethereum ABI encoding & decoding. | |
| 13 | +public struct EthereumAbi { | |
| 14 | + | |
| 15 | + /// Decode a contract call (function input) according to an ABI json. | |
| 16 | + /// | |
| 17 | + /// - Parameter coin: EVM-compatible coin type. | |
| 18 | + /// - Parameter input: The serialized data of `TW.EthereumAbi.Proto.ContractCallDecodingInput`. | |
| 19 | + /// - Returns: The serialized data of a `TW.EthereumAbi.Proto.ContractCallDecodingOutput` proto object. | |
| 20 | + public static func decodeContractCall(coin: CoinType, input: Data) -> Data { | |
| 21 | + let inputData = TWDataCreateWithNSData(input) | |
| 22 | + defer { | |
| 23 | + TWDataDelete(inputData) | |
| 24 | + } | |
| 25 | + return TWDataNSData(TWEthereumAbiDecodeContractCall(TWCoinType(rawValue: coin.rawValue), inputData)) | |
| 26 | + } | |
| 27 | + | |
| 28 | + /// Decode a function input or output data according to a given ABI. | |
| 29 | + /// | |
| 30 | + /// - Parameter coin: EVM-compatible coin type. | |
| 31 | + /// - Parameter input: The serialized data of `TW.EthereumAbi.Proto.ParamsDecodingInput`. | |
| 32 | + /// - Returns: The serialized data of a `TW.EthereumAbi.Proto.ParamsDecodingOutput` proto object. | |
| 33 | + public static func decodeParams(coin: CoinType, input: Data) -> Data { | |
| 34 | + let inputData = TWDataCreateWithNSData(input) | |
| 35 | + defer { | |
| 36 | + TWDataDelete(inputData) | |
| 37 | + } | |
| 38 | + return TWDataNSData(TWEthereumAbiDecodeParams(TWCoinType(rawValue: coin.rawValue), inputData)) | |
| 39 | + } | |
| 40 | + | |
| 41 | + /// /// Decodes an Eth ABI value according to a given type. | |
| 42 | + /// | |
| 43 | + /// - Parameter coin: EVM-compatible coin type. | |
| 44 | + /// - Parameter input: The serialized data of `TW.EthereumAbi.Proto.ValueDecodingInput`. | |
| 45 | + /// - Returns: The serialized data of a `TW.EthereumAbi.Proto.ValueDecodingOutput` proto object. | |
| 46 | + public static func decodeValue(coin: CoinType, input: Data) -> Data { | |
| 47 | + let inputData = TWDataCreateWithNSData(input) | |
| 48 | + defer { | |
| 49 | + TWDataDelete(inputData) | |
| 50 | + } | |
| 51 | + return TWDataNSData(TWEthereumAbiDecodeValue(TWCoinType(rawValue: coin.rawValue), inputData)) | |
| 52 | + } | |
| 53 | + | |
| 54 | + /// Encode function to Eth ABI binary. | |
| 55 | + /// | |
| 56 | + /// - Parameter coin: EVM-compatible coin type. | |
| 57 | + /// - Parameter input: The serialized data of `TW.EthereumAbi.Proto.FunctionEncodingInput`. | |
| 58 | + /// - Returns: The serialized data of a `TW.EthereumAbi.Proto.FunctionEncodingOutput` proto object. | |
| 59 | + public static func encodeFunction(coin: CoinType, input: Data) -> Data { | |
| 60 | + let inputData = TWDataCreateWithNSData(input) | |
| 61 | + defer { | |
| 62 | + TWDataDelete(inputData) | |
| 63 | + } | |
| 64 | + return TWDataNSData(TWEthereumAbiEncodeFunction(TWCoinType(rawValue: coin.rawValue), inputData)) | |
| 65 | + } | |
| 66 | + | |
| 67 | + /// Encode function to Eth ABI binary | |
| 68 | + /// | |
| 69 | + /// - Parameter fn: Non-null Eth abi function | |
| 70 | + /// - Returns: Non-null encoded block of data | |
| 71 | + public static func encode(fn: EthereumAbiFunction) -> Data { | |
| 72 | + return TWDataNSData(TWEthereumAbiEncode(fn.rawValue)) | |
| 73 | + } | |
| 74 | + | |
| 75 | + /// Decode function output from Eth ABI binary, fill output parameters | |
| 76 | + /// | |
| 77 | + /// \param[in] fn Non-null Eth abi function | |
| 78 | + /// \param[out] encoded Non-null block of data | |
| 79 | + /// - Returns: true if encoded have been filled correctly, false otherwise | |
| 80 | + public static func decodeOutput(fn: EthereumAbiFunction, encoded: Data) -> Bool { | |
| 81 | + let encodedData = TWDataCreateWithNSData(encoded) | |
| 82 | + defer { | |
| 83 | + TWDataDelete(encodedData) | |
| 84 | + } | |
| 85 | + return TWEthereumAbiDecodeOutput(fn.rawValue, encodedData) | |
| 86 | + } | |
| 87 | + | |
| 88 | + /// Decode function call data to human readable json format, according to input abi json | |
| 89 | + /// | |
| 90 | + /// - Parameter data: Non-null block of data | |
| 91 | + /// - Parameter abi: Non-null string | |
| 92 | + /// - Returns: Non-null json string function call data | |
| 93 | + public static func decodeCall(data: Data, abi: String) -> String? { | |
| 94 | + let dataData = TWDataCreateWithNSData(data) | |
| 95 | + defer { | |
| 96 | + TWDataDelete(dataData) | |
| 97 | + } | |
| 98 | + let abiString = TWStringCreateWithNSString(abi) | |
| 99 | + defer { | |
| 100 | + TWStringDelete(abiString) | |
| 101 | + } | |
| 102 | + guard let result = TWEthereumAbiDecodeCall(dataData, abiString) else { | |
| 103 | + return nil | |
| 104 | + } | |
| 105 | + return TWStringNSString(result) | |
| 106 | + } | |
| 107 | + | |
| 108 | + /// Compute the hash of a struct, used for signing, according to EIP712 ("v4"). | |
| 109 | + /// Input is a Json object (as string), with following fields: | |
| 110 | + /// - types: map of used struct types (see makeTypes()) | |
| 111 | + /// - primaryType: the type of the message (string) | |
| 112 | + /// - domain: EIP712 domain specifier values | |
| 113 | + /// - message: the message (object). | |
| 114 | + /// Throws on error. | |
| 115 | + /// Example input: | |
| 116 | + /// R"({ | |
| 117 | + /// "types": { | |
| 118 | + /// "EIP712Domain": [ | |
| 119 | + /// {"name": "name", "type": "string"}, | |
| 120 | + /// {"name": "version", "type": "string"}, | |
| 121 | + /// {"name": "chainId", "type": "uint256"}, | |
| 122 | + /// {"name": "verifyingContract", "type": "address"} | |
| 123 | + /// ], | |
| 124 | + /// "Person": [ | |
| 125 | + /// {"name": "name", "type": "string"}, | |
| 126 | + /// {"name": "wallet", "type": "address"} | |
| 127 | + /// ] | |
| 128 | + /// }, | |
| 129 | + /// "primaryType": "Person", | |
| 130 | + /// "domain": { | |
| 131 | + /// "name": "Ether Person", | |
| 132 | + /// "version": "1", | |
| 133 | + /// "chainId": 1, | |
| 134 | + /// "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" | |
| 135 | + /// }, | |
| 136 | + /// "message": { | |
| 137 | + /// "name": "Cow", | |
| 138 | + /// "wallet": "CD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | |
| 139 | + /// } | |
| 140 | + /// })"); | |
| 141 | + /// On error, empty Data is returned. | |
| 142 | + /// Returned data must be deleted (hint: use WRAPD() macro). | |
| 143 | + /// | |
| 144 | + /// - Parameter messageJson: Non-null json abi input | |
| 145 | + /// - Returns: Non-null block of data, encoded abi input | |
| 146 | + public static func encodeTyped(messageJson: String) -> Data { | |
| 147 | + let messageJsonString = TWStringCreateWithNSString(messageJson) | |
| 148 | + defer { | |
| 149 | + TWStringDelete(messageJsonString) | |
| 150 | + } | |
| 151 | + return TWDataNSData(TWEthereumAbiEncodeTyped(messageJsonString)) | |
| 152 | + } | |
| 153 | + | |
| 154 | + /// Get function signature from Ethereum ABI json | |
| 155 | + /// | |
| 156 | + /// - Parameter abi: The function ABI json string, for example: {"inputs":[{"internalType":"bool","name":"arg1","type":"bool"}],"name":"fun1","outputs":[],"stateMutability":"nonpayable","type":"function"} | |
| 157 | + /// - Returns: the function type signature, of the form "baz(int32,uint256)", null if the abi is invalid. | |
| 158 | + public static func getFunctionSignature(abi: String) -> String? { | |
| 159 | + let abiString = TWStringCreateWithNSString(abi) | |
| 160 | + defer { | |
| 161 | + TWStringDelete(abiString) | |
| 162 | + } | |
| 163 | + guard let result = TWEthereumAbiGetFunctionSignature(abiString) else { | |
| 164 | + return nil | |
| 165 | + } | |
| 166 | + return TWStringNSString(result) | |
| 167 | + } | |
| 168 | + | |
| 169 | + | |
| 170 | + init() { | |
| 171 | + } | |
| 172 | + | |
| 173 | + | |
| 174 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/EthereumAbiFunction.swift
+560 −0
@@ -0,0 +1,560 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents Ethereum ABI function | |
| 13 | +public final class EthereumAbiFunction { | |
| 14 | + | |
| 15 | + let rawValue: OpaquePointer | |
| 16 | + | |
| 17 | + init(rawValue: OpaquePointer) { | |
| 18 | + self.rawValue = rawValue | |
| 19 | + } | |
| 20 | + | |
| 21 | + public init(name: String) { | |
| 22 | + let nameString = TWStringCreateWithNSString(name) | |
| 23 | + defer { | |
| 24 | + TWStringDelete(nameString) | |
| 25 | + } | |
| 26 | + rawValue = TWEthereumAbiFunctionCreateWithString(nameString) | |
| 27 | + } | |
| 28 | + | |
| 29 | + deinit { | |
| 30 | + TWEthereumAbiFunctionDelete(rawValue) | |
| 31 | + } | |
| 32 | + | |
| 33 | + /// Return the function type signature, of the form "baz(int32,uint256)" | |
| 34 | + /// | |
| 35 | + /// - Parameter fn: A Non-null eth abi function | |
| 36 | + /// - Returns: function type signature as a Non-null string. | |
| 37 | + public func getType() -> String { | |
| 38 | + return TWStringNSString(TWEthereumAbiFunctionGetType(rawValue)) | |
| 39 | + } | |
| 40 | + | |
| 41 | + /// Methods for adding parameters of the given type (input or output). | |
| 42 | + /// For output parameters (isOutput=true) a value has to be specified, although usually not need; | |
| 43 | + /// Add a uint8 type parameter | |
| 44 | + /// | |
| 45 | + /// - Parameter fn: A Non-null eth abi function | |
| 46 | + /// - Parameter val: for output parameters, value has to be specified | |
| 47 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 48 | + /// - Returns: the index of the parameter (0-based). | |
| 49 | + @discardableResult | |
| 50 | + public func addParamUInt8(val: UInt8, isOutput: Bool) -> Int32 { | |
| 51 | + return TWEthereumAbiFunctionAddParamUInt8(rawValue, val, isOutput) | |
| 52 | + } | |
| 53 | + | |
| 54 | + /// Add a uint16 type parameter | |
| 55 | + /// | |
| 56 | + /// - Parameter fn: A Non-null eth abi function | |
| 57 | + /// - Parameter val: for output parameters, value has to be specified | |
| 58 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 59 | + /// - Returns: the index of the parameter (0-based). | |
| 60 | + @discardableResult | |
| 61 | + public func addParamUInt16(val: UInt16, isOutput: Bool) -> Int32 { | |
| 62 | + return TWEthereumAbiFunctionAddParamUInt16(rawValue, val, isOutput) | |
| 63 | + } | |
| 64 | + | |
| 65 | + /// Add a uint32 type parameter | |
| 66 | + /// | |
| 67 | + /// - Parameter fn: A Non-null eth abi function | |
| 68 | + /// - Parameter val: for output parameters, value has to be specified | |
| 69 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 70 | + /// - Returns: the index of the parameter (0-based). | |
| 71 | + @discardableResult | |
| 72 | + public func addParamUInt32(val: UInt32, isOutput: Bool) -> Int32 { | |
| 73 | + return TWEthereumAbiFunctionAddParamUInt32(rawValue, val, isOutput) | |
| 74 | + } | |
| 75 | + | |
| 76 | + /// Add a uint64 type parameter | |
| 77 | + /// | |
| 78 | + /// - Parameter fn: A Non-null eth abi function | |
| 79 | + /// - Parameter val: for output parameters, value has to be specified | |
| 80 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 81 | + /// - Returns: the index of the parameter (0-based). | |
| 82 | + @discardableResult | |
| 83 | + public func addParamUInt64(val: UInt64, isOutput: Bool) -> Int32 { | |
| 84 | + return TWEthereumAbiFunctionAddParamUInt64(rawValue, val, isOutput) | |
| 85 | + } | |
| 86 | + | |
| 87 | + /// Add a uint256 type parameter | |
| 88 | + /// | |
| 89 | + /// - Parameter fn: A Non-null eth abi function | |
| 90 | + /// - Parameter val: for output parameters, value has to be specified | |
| 91 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 92 | + /// - Returns: the index of the parameter (0-based). | |
| 93 | + @discardableResult | |
| 94 | + public func addParamUInt256(val: Data, isOutput: Bool) -> Int32 { | |
| 95 | + let valData = TWDataCreateWithNSData(val) | |
| 96 | + defer { | |
| 97 | + TWDataDelete(valData) | |
| 98 | + } | |
| 99 | + return TWEthereumAbiFunctionAddParamUInt256(rawValue, valData, isOutput) | |
| 100 | + } | |
| 101 | + | |
| 102 | + /// Add a uint(bits) type parameter | |
| 103 | + /// | |
| 104 | + /// - Parameter fn: A Non-null eth abi function | |
| 105 | + /// - Parameter val: for output parameters, value has to be specified | |
| 106 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 107 | + /// - Returns: the index of the parameter (0-based). | |
| 108 | + @discardableResult | |
| 109 | + public func addParamUIntN(bits: Int32, val: Data, isOutput: Bool) -> Int32 { | |
| 110 | + let valData = TWDataCreateWithNSData(val) | |
| 111 | + defer { | |
| 112 | + TWDataDelete(valData) | |
| 113 | + } | |
| 114 | + return TWEthereumAbiFunctionAddParamUIntN(rawValue, Int32(bits), valData, isOutput) | |
| 115 | + } | |
| 116 | + | |
| 117 | + /// Add a int8 type parameter | |
| 118 | + /// | |
| 119 | + /// - Parameter fn: A Non-null eth abi function | |
| 120 | + /// - Parameter val: for output parameters, value has to be specified | |
| 121 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 122 | + /// - Returns: the index of the parameter (0-based). | |
| 123 | + @discardableResult | |
| 124 | + public func addParamInt8(val: Int8, isOutput: Bool) -> Int32 { | |
| 125 | + return TWEthereumAbiFunctionAddParamInt8(rawValue, val, isOutput) | |
| 126 | + } | |
| 127 | + | |
| 128 | + /// Add a int16 type parameter | |
| 129 | + /// | |
| 130 | + /// - Parameter fn: A Non-null eth abi function | |
| 131 | + /// - Parameter val: for output parameters, value has to be specified | |
| 132 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 133 | + /// - Returns: the index of the parameter (0-based). | |
| 134 | + @discardableResult | |
| 135 | + public func addParamInt16(val: Int16, isOutput: Bool) -> Int32 { | |
| 136 | + return TWEthereumAbiFunctionAddParamInt16(rawValue, val, isOutput) | |
| 137 | + } | |
| 138 | + | |
| 139 | + /// Add a int32 type parameter | |
| 140 | + /// | |
| 141 | + /// - Parameter fn: A Non-null eth abi function | |
| 142 | + /// - Parameter val: for output parameters, value has to be specified | |
| 143 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 144 | + /// - Returns: the index of the parameter (0-based). | |
| 145 | + @discardableResult | |
| 146 | + public func addParamInt32(val: Int32, isOutput: Bool) -> Int32 { | |
| 147 | + return TWEthereumAbiFunctionAddParamInt32(rawValue, val, isOutput) | |
| 148 | + } | |
| 149 | + | |
| 150 | + /// Add a int64 type parameter | |
| 151 | + /// | |
| 152 | + /// - Parameter fn: A Non-null eth abi function | |
| 153 | + /// - Parameter val: for output parameters, value has to be specified | |
| 154 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 155 | + /// - Returns: the index of the parameter (0-based). | |
| 156 | + @discardableResult | |
| 157 | + public func addParamInt64(val: Int64, isOutput: Bool) -> Int32 { | |
| 158 | + return TWEthereumAbiFunctionAddParamInt64(rawValue, val, isOutput) | |
| 159 | + } | |
| 160 | + | |
| 161 | + /// Add a int256 type parameter | |
| 162 | + /// | |
| 163 | + /// - Parameter fn: A Non-null eth abi function | |
| 164 | + /// - Parameter val: for output parameters, value has to be specified (stored in a block of data) | |
| 165 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 166 | + /// - Returns: the index of the parameter (0-based). | |
| 167 | + @discardableResult | |
| 168 | + public func addParamInt256(val: Data, isOutput: Bool) -> Int32 { | |
| 169 | + let valData = TWDataCreateWithNSData(val) | |
| 170 | + defer { | |
| 171 | + TWDataDelete(valData) | |
| 172 | + } | |
| 173 | + return TWEthereumAbiFunctionAddParamInt256(rawValue, valData, isOutput) | |
| 174 | + } | |
| 175 | + | |
| 176 | + /// Add a int(bits) type parameter | |
| 177 | + /// | |
| 178 | + /// - Parameter fn: A Non-null eth abi function | |
| 179 | + /// - Parameter bits: Number of bits of the integer parameter | |
| 180 | + /// - Parameter val: for output parameters, value has to be specified | |
| 181 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 182 | + /// - Returns: the index of the parameter (0-based). | |
| 183 | + @discardableResult | |
| 184 | + public func addParamIntN(bits: Int32, val: Data, isOutput: Bool) -> Int32 { | |
| 185 | + let valData = TWDataCreateWithNSData(val) | |
| 186 | + defer { | |
| 187 | + TWDataDelete(valData) | |
| 188 | + } | |
| 189 | + return TWEthereumAbiFunctionAddParamIntN(rawValue, Int32(bits), valData, isOutput) | |
| 190 | + } | |
| 191 | + | |
| 192 | + /// Add a bool type parameter | |
| 193 | + /// | |
| 194 | + /// - Parameter fn: A Non-null eth abi function | |
| 195 | + /// - Parameter val: for output parameters, value has to be specified | |
| 196 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 197 | + /// - Returns: the index of the parameter (0-based). | |
| 198 | + @discardableResult | |
| 199 | + public func addParamBool(val: Bool, isOutput: Bool) -> Int32 { | |
| 200 | + return TWEthereumAbiFunctionAddParamBool(rawValue, val, isOutput) | |
| 201 | + } | |
| 202 | + | |
| 203 | + /// Add a string type parameter | |
| 204 | + /// | |
| 205 | + /// - Parameter fn: A Non-null eth abi function | |
| 206 | + /// - Parameter val: for output parameters, value has to be specified | |
| 207 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 208 | + /// - Returns: the index of the parameter (0-based). | |
| 209 | + @discardableResult | |
| 210 | + public func addParamString(val: String, isOutput: Bool) -> Int32 { | |
| 211 | + let valString = TWStringCreateWithNSString(val) | |
| 212 | + defer { | |
| 213 | + TWStringDelete(valString) | |
| 214 | + } | |
| 215 | + return TWEthereumAbiFunctionAddParamString(rawValue, valString, isOutput) | |
| 216 | + } | |
| 217 | + | |
| 218 | + /// Add an address type parameter | |
| 219 | + /// | |
| 220 | + /// - Parameter fn: A Non-null eth abi function | |
| 221 | + /// - Parameter val: for output parameters, value has to be specified | |
| 222 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 223 | + /// - Returns: the index of the parameter (0-based). | |
| 224 | + @discardableResult | |
| 225 | + public func addParamAddress(val: Data, isOutput: Bool) -> Int32 { | |
| 226 | + let valData = TWDataCreateWithNSData(val) | |
| 227 | + defer { | |
| 228 | + TWDataDelete(valData) | |
| 229 | + } | |
| 230 | + return TWEthereumAbiFunctionAddParamAddress(rawValue, valData, isOutput) | |
| 231 | + } | |
| 232 | + | |
| 233 | + /// Add a bytes type parameter | |
| 234 | + /// | |
| 235 | + /// - Parameter fn: A Non-null eth abi function | |
| 236 | + /// - Parameter val: for output parameters, value has to be specified | |
| 237 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 238 | + /// - Returns: the index of the parameter (0-based). | |
| 239 | + @discardableResult | |
| 240 | + public func addParamBytes(val: Data, isOutput: Bool) -> Int32 { | |
| 241 | + let valData = TWDataCreateWithNSData(val) | |
| 242 | + defer { | |
| 243 | + TWDataDelete(valData) | |
| 244 | + } | |
| 245 | + return TWEthereumAbiFunctionAddParamBytes(rawValue, valData, isOutput) | |
| 246 | + } | |
| 247 | + | |
| 248 | + /// Add a bytes[N] type parameter | |
| 249 | + /// | |
| 250 | + /// - Parameter fn: A Non-null eth abi function | |
| 251 | + /// - Parameter size: fixed size of the bytes array parameter (val). | |
| 252 | + /// - Parameter val: for output parameters, value has to be specified | |
| 253 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 254 | + /// - Returns: the index of the parameter (0-based). | |
| 255 | + @discardableResult | |
| 256 | + public func addParamBytesFix(size: Int, val: Data, isOutput: Bool) -> Int32 { | |
| 257 | + let valData = TWDataCreateWithNSData(val) | |
| 258 | + defer { | |
| 259 | + TWDataDelete(valData) | |
| 260 | + } | |
| 261 | + return TWEthereumAbiFunctionAddParamBytesFix(rawValue, size, valData, isOutput) | |
| 262 | + } | |
| 263 | + | |
| 264 | + /// Add a type[] type parameter | |
| 265 | + /// | |
| 266 | + /// - Parameter fn: A Non-null eth abi function | |
| 267 | + /// - Parameter val: for output parameters, value has to be specified | |
| 268 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 269 | + /// - Returns: the index of the parameter (0-based). | |
| 270 | + @discardableResult | |
| 271 | + public func addParamArray(isOutput: Bool) -> Int32 { | |
| 272 | + return TWEthereumAbiFunctionAddParamArray(rawValue, isOutput) | |
| 273 | + } | |
| 274 | + | |
| 275 | + /// Methods for accessing the value of an output or input parameter, of different types. | |
| 276 | + /// Get a uint8 type parameter at the given index | |
| 277 | + /// | |
| 278 | + /// - Parameter fn: A Non-null eth abi function | |
| 279 | + /// - Parameter idx: index for the parameter (0-based). | |
| 280 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 281 | + /// - Returns: the value of the parameter. | |
| 282 | + public func getParamUInt8(idx: Int32, isOutput: Bool) -> UInt8 { | |
| 283 | + return TWEthereumAbiFunctionGetParamUInt8(rawValue, Int32(idx), isOutput) | |
| 284 | + } | |
| 285 | + | |
| 286 | + /// Get a uint64 type parameter at the given index | |
| 287 | + /// | |
| 288 | + /// - Parameter fn: A Non-null eth abi function | |
| 289 | + /// - Parameter idx: index for the parameter (0-based). | |
| 290 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 291 | + /// - Returns: the value of the parameter. | |
| 292 | + public func getParamUInt64(idx: Int32, isOutput: Bool) -> UInt64 { | |
| 293 | + return TWEthereumAbiFunctionGetParamUInt64(rawValue, Int32(idx), isOutput) | |
| 294 | + } | |
| 295 | + | |
| 296 | + /// Get a uint256 type parameter at the given index | |
| 297 | + /// | |
| 298 | + /// - Parameter fn: A Non-null eth abi function | |
| 299 | + /// - Parameter idx: index for the parameter (0-based). | |
| 300 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 301 | + /// - Returns: the value of the parameter stored in a block of data. | |
| 302 | + public func getParamUInt256(idx: Int32, isOutput: Bool) -> Data { | |
| 303 | + return TWDataNSData(TWEthereumAbiFunctionGetParamUInt256(rawValue, Int32(idx), isOutput)) | |
| 304 | + } | |
| 305 | + | |
| 306 | + /// Get a bool type parameter at the given index | |
| 307 | + /// | |
| 308 | + /// - Parameter fn: A Non-null eth abi function | |
| 309 | + /// - Parameter idx: index for the parameter (0-based). | |
| 310 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 311 | + /// - Returns: the value of the parameter. | |
| 312 | + public func getParamBool(idx: Int32, isOutput: Bool) -> Bool { | |
| 313 | + return TWEthereumAbiFunctionGetParamBool(rawValue, Int32(idx), isOutput) | |
| 314 | + } | |
| 315 | + | |
| 316 | + /// Get a string type parameter at the given index | |
| 317 | + /// | |
| 318 | + /// - Parameter fn: A Non-null eth abi function | |
| 319 | + /// - Parameter idx: index for the parameter (0-based). | |
| 320 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 321 | + /// - Returns: the value of the parameter. | |
| 322 | + public func getParamString(idx: Int32, isOutput: Bool) -> String { | |
| 323 | + return TWStringNSString(TWEthereumAbiFunctionGetParamString(rawValue, Int32(idx), isOutput)) | |
| 324 | + } | |
| 325 | + | |
| 326 | + /// Get an address type parameter at the given index | |
| 327 | + /// | |
| 328 | + /// - Parameter fn: A Non-null eth abi function | |
| 329 | + /// - Parameter idx: index for the parameter (0-based). | |
| 330 | + /// - Parameter isOutput: determines if the parameter is an input or output | |
| 331 | + /// - Returns: the value of the parameter. | |
| 332 | + public func getParamAddress(idx: Int32, isOutput: Bool) -> Data { | |
| 333 | + return TWDataNSData(TWEthereumAbiFunctionGetParamAddress(rawValue, Int32(idx), isOutput)) | |
| 334 | + } | |
| 335 | + | |
| 336 | + /// Methods for adding a parameter of the given type to a top-level input parameter array. Returns the index of the parameter (0-based). | |
| 337 | + /// Note that nested ParamArrays are not possible through this API, could be done by using index paths like "1/0" | |
| 338 | + /// Adding a uint8 type parameter of to the top-level input parameter array | |
| 339 | + /// | |
| 340 | + /// - Parameter fn: A Non-null eth abi function | |
| 341 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 342 | + /// - Parameter val: the value of the parameter | |
| 343 | + /// - Returns: the index of the added parameter (0-based). | |
| 344 | + @discardableResult | |
| 345 | + public func addInArrayParamUInt8(arrayIdx: Int32, val: UInt8) -> Int32 { | |
| 346 | + return TWEthereumAbiFunctionAddInArrayParamUInt8(rawValue, Int32(arrayIdx), val) | |
| 347 | + } | |
| 348 | + | |
| 349 | + /// Adding a uint16 type parameter of to the top-level input parameter array | |
| 350 | + /// | |
| 351 | + /// - Parameter fn: A Non-null eth abi function | |
| 352 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 353 | + /// - Parameter val: the value of the parameter | |
| 354 | + /// - Returns: the index of the added parameter (0-based). | |
| 355 | + @discardableResult | |
| 356 | + public func addInArrayParamUInt16(arrayIdx: Int32, val: UInt16) -> Int32 { | |
| 357 | + return TWEthereumAbiFunctionAddInArrayParamUInt16(rawValue, Int32(arrayIdx), val) | |
| 358 | + } | |
| 359 | + | |
| 360 | + /// Adding a uint32 type parameter of to the top-level input parameter array | |
| 361 | + /// | |
| 362 | + /// - Parameter fn: A Non-null eth abi function | |
| 363 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 364 | + /// - Parameter val: the value of the parameter | |
| 365 | + /// - Returns: the index of the added parameter (0-based). | |
| 366 | + @discardableResult | |
| 367 | + public func addInArrayParamUInt32(arrayIdx: Int32, val: UInt32) -> Int32 { | |
| 368 | + return TWEthereumAbiFunctionAddInArrayParamUInt32(rawValue, Int32(arrayIdx), val) | |
| 369 | + } | |
| 370 | + | |
| 371 | + /// Adding a uint64 type parameter of to the top-level input parameter array | |
| 372 | + /// | |
| 373 | + /// - Parameter fn: A Non-null eth abi function | |
| 374 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 375 | + /// - Parameter val: the value of the parameter | |
| 376 | + /// - Returns: the index of the added parameter (0-based). | |
| 377 | + @discardableResult | |
| 378 | + public func addInArrayParamUInt64(arrayIdx: Int32, val: UInt64) -> Int32 { | |
| 379 | + return TWEthereumAbiFunctionAddInArrayParamUInt64(rawValue, Int32(arrayIdx), val) | |
| 380 | + } | |
| 381 | + | |
| 382 | + /// Adding a uint256 type parameter of to the top-level input parameter array | |
| 383 | + /// | |
| 384 | + /// - Parameter fn: A Non-null eth abi function | |
| 385 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 386 | + /// - Parameter val: the value of the parameter stored in a block of data | |
| 387 | + /// - Returns: the index of the added parameter (0-based). | |
| 388 | + @discardableResult | |
| 389 | + public func addInArrayParamUInt256(arrayIdx: Int32, val: Data) -> Int32 { | |
| 390 | + let valData = TWDataCreateWithNSData(val) | |
| 391 | + defer { | |
| 392 | + TWDataDelete(valData) | |
| 393 | + } | |
| 394 | + return TWEthereumAbiFunctionAddInArrayParamUInt256(rawValue, Int32(arrayIdx), valData) | |
| 395 | + } | |
| 396 | + | |
| 397 | + /// Adding a uint[N] type parameter of to the top-level input parameter array | |
| 398 | + /// | |
| 399 | + /// - Parameter fn: A Non-null eth abi function | |
| 400 | + /// - Parameter bits: Number of bits of the integer parameter | |
| 401 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 402 | + /// - Parameter val: the value of the parameter stored in a block of data | |
| 403 | + /// - Returns: the index of the added parameter (0-based). | |
| 404 | + @discardableResult | |
| 405 | + public func addInArrayParamUIntN(arrayIdx: Int32, bits: Int32, val: Data) -> Int32 { | |
| 406 | + let valData = TWDataCreateWithNSData(val) | |
| 407 | + defer { | |
| 408 | + TWDataDelete(valData) | |
| 409 | + } | |
| 410 | + return TWEthereumAbiFunctionAddInArrayParamUIntN(rawValue, Int32(arrayIdx), Int32(bits), valData) | |
| 411 | + } | |
| 412 | + | |
| 413 | + /// Adding a int8 type parameter of to the top-level input parameter array | |
| 414 | + /// | |
| 415 | + /// - Parameter fn: A Non-null eth abi function | |
| 416 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 417 | + /// - Parameter val: the value of the parameter | |
| 418 | + /// - Returns: the index of the added parameter (0-based). | |
| 419 | + @discardableResult | |
| 420 | + public func addInArrayParamInt8(arrayIdx: Int32, val: Int8) -> Int32 { | |
| 421 | + return TWEthereumAbiFunctionAddInArrayParamInt8(rawValue, Int32(arrayIdx), val) | |
| 422 | + } | |
| 423 | + | |
| 424 | + /// Adding a int16 type parameter of to the top-level input parameter array | |
| 425 | + /// | |
| 426 | + /// - Parameter fn: A Non-null eth abi function | |
| 427 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 428 | + /// - Parameter val: the value of the parameter | |
| 429 | + /// - Returns: the index of the added parameter (0-based). | |
| 430 | + @discardableResult | |
| 431 | + public func addInArrayParamInt16(arrayIdx: Int32, val: Int16) -> Int32 { | |
| 432 | + return TWEthereumAbiFunctionAddInArrayParamInt16(rawValue, Int32(arrayIdx), val) | |
| 433 | + } | |
| 434 | + | |
| 435 | + /// Adding a int32 type parameter of to the top-level input parameter array | |
| 436 | + /// | |
| 437 | + /// - Parameter fn: A Non-null eth abi function | |
| 438 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 439 | + /// - Parameter val: the value of the parameter | |
| 440 | + /// - Returns: the index of the added parameter (0-based). | |
| 441 | + @discardableResult | |
| 442 | + public func addInArrayParamInt32(arrayIdx: Int32, val: Int32) -> Int32 { | |
| 443 | + return TWEthereumAbiFunctionAddInArrayParamInt32(rawValue, Int32(arrayIdx), val) | |
| 444 | + } | |
| 445 | + | |
| 446 | + /// Adding a int64 type parameter of to the top-level input parameter array | |
| 447 | + /// | |
| 448 | + /// - Parameter fn: A Non-null eth abi function | |
| 449 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 450 | + /// - Parameter val: the value of the parameter | |
| 451 | + /// - Returns: the index of the added parameter (0-based). | |
| 452 | + @discardableResult | |
| 453 | + public func addInArrayParamInt64(arrayIdx: Int32, val: Int64) -> Int32 { | |
| 454 | + return TWEthereumAbiFunctionAddInArrayParamInt64(rawValue, Int32(arrayIdx), val) | |
| 455 | + } | |
| 456 | + | |
| 457 | + /// Adding a int256 type parameter of to the top-level input parameter array | |
| 458 | + /// | |
| 459 | + /// - Parameter fn: A Non-null eth abi function | |
| 460 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 461 | + /// - Parameter val: the value of the parameter stored in a block of data | |
| 462 | + /// - Returns: the index of the added parameter (0-based). | |
| 463 | + @discardableResult | |
| 464 | + public func addInArrayParamInt256(arrayIdx: Int32, val: Data) -> Int32 { | |
| 465 | + let valData = TWDataCreateWithNSData(val) | |
| 466 | + defer { | |
| 467 | + TWDataDelete(valData) | |
| 468 | + } | |
| 469 | + return TWEthereumAbiFunctionAddInArrayParamInt256(rawValue, Int32(arrayIdx), valData) | |
| 470 | + } | |
| 471 | + | |
| 472 | + /// Adding a int[N] type parameter of to the top-level input parameter array | |
| 473 | + /// | |
| 474 | + /// - Parameter fn: A Non-null eth abi function | |
| 475 | + /// - Parameter bits: Number of bits of the integer parameter | |
| 476 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 477 | + /// - Parameter val: the value of the parameter stored in a block of data | |
| 478 | + /// - Returns: the index of the added parameter (0-based). | |
| 479 | + @discardableResult | |
| 480 | + public func addInArrayParamIntN(arrayIdx: Int32, bits: Int32, val: Data) -> Int32 { | |
| 481 | + let valData = TWDataCreateWithNSData(val) | |
| 482 | + defer { | |
| 483 | + TWDataDelete(valData) | |
| 484 | + } | |
| 485 | + return TWEthereumAbiFunctionAddInArrayParamIntN(rawValue, Int32(arrayIdx), Int32(bits), valData) | |
| 486 | + } | |
| 487 | + | |
| 488 | + /// Adding a bool type parameter of to the top-level input parameter array | |
| 489 | + /// | |
| 490 | + /// - Parameter fn: A Non-null eth abi function | |
| 491 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 492 | + /// - Parameter val: the value of the parameter | |
| 493 | + /// - Returns: the index of the added parameter (0-based). | |
| 494 | + @discardableResult | |
| 495 | + public func addInArrayParamBool(arrayIdx: Int32, val: Bool) -> Int32 { | |
| 496 | + return TWEthereumAbiFunctionAddInArrayParamBool(rawValue, Int32(arrayIdx), val) | |
| 497 | + } | |
| 498 | + | |
| 499 | + /// Adding a string type parameter of to the top-level input parameter array | |
| 500 | + /// | |
| 501 | + /// - Parameter fn: A Non-null eth abi function | |
| 502 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 503 | + /// - Parameter val: the value of the parameter | |
| 504 | + /// - Returns: the index of the added parameter (0-based). | |
| 505 | + @discardableResult | |
| 506 | + public func addInArrayParamString(arrayIdx: Int32, val: String) -> Int32 { | |
| 507 | + let valString = TWStringCreateWithNSString(val) | |
| 508 | + defer { | |
| 509 | + TWStringDelete(valString) | |
| 510 | + } | |
| 511 | + return TWEthereumAbiFunctionAddInArrayParamString(rawValue, Int32(arrayIdx), valString) | |
| 512 | + } | |
| 513 | + | |
| 514 | + /// Adding an address type parameter of to the top-level input parameter array | |
| 515 | + /// | |
| 516 | + /// - Parameter fn: A Non-null eth abi function | |
| 517 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 518 | + /// - Parameter val: the value of the parameter | |
| 519 | + /// - Returns: the index of the added parameter (0-based). | |
| 520 | + @discardableResult | |
| 521 | + public func addInArrayParamAddress(arrayIdx: Int32, val: Data) -> Int32 { | |
| 522 | + let valData = TWDataCreateWithNSData(val) | |
| 523 | + defer { | |
| 524 | + TWDataDelete(valData) | |
| 525 | + } | |
| 526 | + return TWEthereumAbiFunctionAddInArrayParamAddress(rawValue, Int32(arrayIdx), valData) | |
| 527 | + } | |
| 528 | + | |
| 529 | + /// Adding a bytes type parameter of to the top-level input parameter array | |
| 530 | + /// | |
| 531 | + /// - Parameter fn: A Non-null eth abi function | |
| 532 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 533 | + /// - Parameter val: the value of the parameter | |
| 534 | + /// - Returns: the index of the added parameter (0-based). | |
| 535 | + @discardableResult | |
| 536 | + public func addInArrayParamBytes(arrayIdx: Int32, val: Data) -> Int32 { | |
| 537 | + let valData = TWDataCreateWithNSData(val) | |
| 538 | + defer { | |
| 539 | + TWDataDelete(valData) | |
| 540 | + } | |
| 541 | + return TWEthereumAbiFunctionAddInArrayParamBytes(rawValue, Int32(arrayIdx), valData) | |
| 542 | + } | |
| 543 | + | |
| 544 | + /// Adding a int64 type parameter of to the top-level input parameter array | |
| 545 | + /// | |
| 546 | + /// - Parameter fn: A Non-null eth abi function | |
| 547 | + /// - Parameter arrayIdx: array index for the abi function (0-based). | |
| 548 | + /// - Parameter size: fixed size of the bytes array parameter (val). | |
| 549 | + /// - Parameter val: the value of the parameter | |
| 550 | + /// - Returns: the index of the added parameter (0-based). | |
| 551 | + @discardableResult | |
| 552 | + public func addInArrayParamBytesFix(arrayIdx: Int32, size: Int, val: Data) -> Int32 { | |
| 553 | + let valData = TWDataCreateWithNSData(val) | |
| 554 | + defer { | |
| 555 | + TWDataDelete(valData) | |
| 556 | + } | |
| 557 | + return TWEthereumAbiFunctionAddInArrayParamBytesFix(rawValue, Int32(arrayIdx), size, valData) | |
| 558 | + } | |
| 559 | + | |
| 560 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/EthereumAbiValue.swift
+162 −0
@@ -0,0 +1,162 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents Ethereum ABI value | |
| 13 | +public struct EthereumAbiValue { | |
| 14 | + | |
| 15 | + /// Encode a bool according to Ethereum ABI, into 32 bytes. Values are padded by 0 on the left, unless specified otherwise | |
| 16 | + /// | |
| 17 | + /// - Parameter value: a boolean value | |
| 18 | + /// - Returns: Encoded value stored in a block of data | |
| 19 | + public static func encodeBool(value: Bool) -> Data { | |
| 20 | + return TWDataNSData(TWEthereumAbiValueEncodeBool(value)) | |
| 21 | + } | |
| 22 | + | |
| 23 | + /// Encode a int32 according to Ethereum ABI, into 32 bytes. Values are padded by 0 on the left, unless specified otherwise | |
| 24 | + /// | |
| 25 | + /// - Parameter value: a int32 value | |
| 26 | + /// - Returns: Encoded value stored in a block of data | |
| 27 | + public static func encodeInt32(value: Int32) -> Data { | |
| 28 | + return TWDataNSData(TWEthereumAbiValueEncodeInt32(value)) | |
| 29 | + } | |
| 30 | + | |
| 31 | + /// Encode a uint32 according to Ethereum ABI, into 32 bytes. Values are padded by 0 on the left, unless specified otherwise | |
| 32 | + /// | |
| 33 | + /// - Parameter value: a uint32 value | |
| 34 | + /// - Returns: Encoded value stored in a block of data | |
| 35 | + public static func encodeUInt32(value: UInt32) -> Data { | |
| 36 | + return TWDataNSData(TWEthereumAbiValueEncodeUInt32(value)) | |
| 37 | + } | |
| 38 | + | |
| 39 | + /// Encode a int256 according to Ethereum ABI, into 32 bytes. Values are padded by 0 on the left, unless specified otherwise | |
| 40 | + /// | |
| 41 | + /// - Parameter value: a int256 value stored in a block of data | |
| 42 | + /// - Returns: Encoded value stored in a block of data | |
| 43 | + public static func encodeInt256(value: Data) -> Data { | |
| 44 | + let valueData = TWDataCreateWithNSData(value) | |
| 45 | + defer { | |
| 46 | + TWDataDelete(valueData) | |
| 47 | + } | |
| 48 | + return TWDataNSData(TWEthereumAbiValueEncodeInt256(valueData)) | |
| 49 | + } | |
| 50 | + | |
| 51 | + /// Encode an int256 according to Ethereum ABI, into 32 bytes. Values are padded by 0 on the left, unless specified otherwise | |
| 52 | + /// | |
| 53 | + /// - Parameter value: a int256 value stored in a block of data | |
| 54 | + /// - Returns: Encoded value stored in a block of data | |
| 55 | + public static func encodeUInt256(value: Data) -> Data { | |
| 56 | + let valueData = TWDataCreateWithNSData(value) | |
| 57 | + defer { | |
| 58 | + TWDataDelete(valueData) | |
| 59 | + } | |
| 60 | + return TWDataNSData(TWEthereumAbiValueEncodeUInt256(valueData)) | |
| 61 | + } | |
| 62 | + | |
| 63 | + /// Encode an address according to Ethereum ABI, 20 bytes of the address. | |
| 64 | + /// | |
| 65 | + /// - Parameter value: an address value stored in a block of data | |
| 66 | + /// - Returns: Encoded value stored in a block of data | |
| 67 | + public static func encodeAddress(value: Data) -> Data { | |
| 68 | + let valueData = TWDataCreateWithNSData(value) | |
| 69 | + defer { | |
| 70 | + TWDataDelete(valueData) | |
| 71 | + } | |
| 72 | + return TWDataNSData(TWEthereumAbiValueEncodeAddress(valueData)) | |
| 73 | + } | |
| 74 | + | |
| 75 | + /// Encode a string according to Ethereum ABI by encoding its hash. | |
| 76 | + /// | |
| 77 | + /// - Parameter value: a string value | |
| 78 | + /// - Returns: Encoded value stored in a block of data | |
| 79 | + public static func encodeString(value: String) -> Data { | |
| 80 | + let valueString = TWStringCreateWithNSString(value) | |
| 81 | + defer { | |
| 82 | + TWStringDelete(valueString) | |
| 83 | + } | |
| 84 | + return TWDataNSData(TWEthereumAbiValueEncodeString(valueString)) | |
| 85 | + } | |
| 86 | + | |
| 87 | + /// Encode a number of bytes, up to 32 bytes, padded on the right. Longer arrays are truncated. | |
| 88 | + /// | |
| 89 | + /// - Parameter value: bunch of bytes | |
| 90 | + /// - Returns: Encoded value stored in a block of data | |
| 91 | + public static func encodeBytes(value: Data) -> Data { | |
| 92 | + let valueData = TWDataCreateWithNSData(value) | |
| 93 | + defer { | |
| 94 | + TWDataDelete(valueData) | |
| 95 | + } | |
| 96 | + return TWDataNSData(TWEthereumAbiValueEncodeBytes(valueData)) | |
| 97 | + } | |
| 98 | + | |
| 99 | + /// Encode a dynamic number of bytes by encoding its hash | |
| 100 | + /// | |
| 101 | + /// - Parameter value: bunch of bytes | |
| 102 | + /// - Returns: Encoded value stored in a block of data | |
| 103 | + public static func encodeBytesDyn(value: Data) -> Data { | |
| 104 | + let valueData = TWDataCreateWithNSData(value) | |
| 105 | + defer { | |
| 106 | + TWDataDelete(valueData) | |
| 107 | + } | |
| 108 | + return TWDataNSData(TWEthereumAbiValueEncodeBytesDyn(valueData)) | |
| 109 | + } | |
| 110 | + | |
| 111 | + /// Decodes input data (bytes longer than 32 will be truncated) as uint256 | |
| 112 | + /// | |
| 113 | + /// - Parameter input: Data to be decoded | |
| 114 | + /// - Returns: Non-null decoded string value | |
| 115 | + public static func decodeUInt256(input: Data) -> String { | |
| 116 | + let inputData = TWDataCreateWithNSData(input) | |
| 117 | + defer { | |
| 118 | + TWDataDelete(inputData) | |
| 119 | + } | |
| 120 | + return TWStringNSString(TWEthereumAbiValueDecodeUInt256(inputData)) | |
| 121 | + } | |
| 122 | + | |
| 123 | + /// Decode an arbitrary type, return value as string | |
| 124 | + /// | |
| 125 | + /// - Parameter input: Data to be decoded | |
| 126 | + /// - Parameter type: the underlying type that need to be decoded | |
| 127 | + /// - Returns: Non-null decoded string value | |
| 128 | + public static func decodeValue(input: Data, type: String) -> String { | |
| 129 | + let inputData = TWDataCreateWithNSData(input) | |
| 130 | + defer { | |
| 131 | + TWDataDelete(inputData) | |
| 132 | + } | |
| 133 | + let typeString = TWStringCreateWithNSString(type) | |
| 134 | + defer { | |
| 135 | + TWStringDelete(typeString) | |
| 136 | + } | |
| 137 | + return TWStringNSString(TWEthereumAbiValueDecodeValue(inputData, typeString)) | |
| 138 | + } | |
| 139 | + | |
| 140 | + /// Decode an array of given simple types. Return a '\n'-separated string of elements | |
| 141 | + /// | |
| 142 | + /// - Parameter input: Data to be decoded | |
| 143 | + /// - Parameter type: the underlying type that need to be decoded | |
| 144 | + /// - Returns: Non-null decoded string value | |
| 145 | + public static func decodeArray(input: Data, type: String) -> String { | |
| 146 | + let inputData = TWDataCreateWithNSData(input) | |
| 147 | + defer { | |
| 148 | + TWDataDelete(inputData) | |
| 149 | + } | |
| 150 | + let typeString = TWStringCreateWithNSString(type) | |
| 151 | + defer { | |
| 152 | + TWStringDelete(typeString) | |
| 153 | + } | |
| 154 | + return TWStringNSString(TWEthereumAbiValueDecodeArray(inputData, typeString)) | |
| 155 | + } | |
| 156 | + | |
| 157 | + | |
| 158 | + init() { | |
| 159 | + } | |
| 160 | + | |
| 161 | + | |
| 162 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/EthereumMessageSigner.swift
+108 −0
@@ -0,0 +1,108 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Ethereum message signing and verification. | |
| 13 | +/// | |
| 14 | +/// Ethereum and some other wallets support a message signing & verification format, to create a proof (a signature) | |
| 15 | +/// that someone has access to the private keys of a specific address. | |
| 16 | +public struct EthereumMessageSigner { | |
| 17 | + | |
| 18 | + /// Sign a typed message EIP-712 V4. | |
| 19 | + /// | |
| 20 | + /// - Parameter privateKey:: the private key used for signing | |
| 21 | + /// - Parameter messageJson:: A custom typed data message in json | |
| 22 | + /// - Returns:s the signature, Hex-encoded. On invalid input empty string is returned. Returned object needs to be deleted after use. | |
| 23 | + public static func signTypedMessage(privateKey: PrivateKey, messageJson: String) -> String { | |
| 24 | + let messageJsonString = TWStringCreateWithNSString(messageJson) | |
| 25 | + defer { | |
| 26 | + TWStringDelete(messageJsonString) | |
| 27 | + } | |
| 28 | + return TWStringNSString(TWEthereumMessageSignerSignTypedMessage(privateKey.rawValue, messageJsonString)) | |
| 29 | + } | |
| 30 | + | |
| 31 | + /// Sign a typed message EIP-712 V4 with EIP-155 replay attack protection. | |
| 32 | + /// | |
| 33 | + /// - Parameter privateKey:: the private key used for signing | |
| 34 | + /// - Parameter messageJson:: A custom typed data message in json | |
| 35 | + /// - Parameter chainId:: chainId for eip-155 protection | |
| 36 | + /// - Returns:s the signature, Hex-encoded. On invalid input empty string is returned or invalid chainId error message. Returned object needs to be deleted after use. | |
| 37 | + public static func signTypedMessageEip155(privateKey: PrivateKey, messageJson: String, chainId: Int32) -> String { | |
| 38 | + let messageJsonString = TWStringCreateWithNSString(messageJson) | |
| 39 | + defer { | |
| 40 | + TWStringDelete(messageJsonString) | |
| 41 | + } | |
| 42 | + return TWStringNSString(TWEthereumMessageSignerSignTypedMessageEip155(privateKey.rawValue, messageJsonString, Int32(chainId))) | |
| 43 | + } | |
| 44 | + | |
| 45 | + /// Sign a message. | |
| 46 | + /// | |
| 47 | + /// - Parameter privateKey:: the private key used for signing | |
| 48 | + /// - Parameter message:: A custom message which is input to the signing. | |
| 49 | + /// - Returns:s the signature, Hex-encoded. On invalid input empty string is returned. Returned object needs to be deleted after use. | |
| 50 | + public static func signMessage(privateKey: PrivateKey, message: String) -> String { | |
| 51 | + let messageString = TWStringCreateWithNSString(message) | |
| 52 | + defer { | |
| 53 | + TWStringDelete(messageString) | |
| 54 | + } | |
| 55 | + return TWStringNSString(TWEthereumMessageSignerSignMessage(privateKey.rawValue, messageString)) | |
| 56 | + } | |
| 57 | + | |
| 58 | + /// Sign a message with Immutable X msg type. | |
| 59 | + /// | |
| 60 | + /// - Parameter privateKey:: the private key used for signing | |
| 61 | + /// - Parameter message:: A custom message which is input to the signing. | |
| 62 | + /// - Returns:s the signature, Hex-encoded. On invalid input empty string is returned. Returned object needs to be deleted after use. | |
| 63 | + public static func signMessageImmutableX(privateKey: PrivateKey, message: String) -> String { | |
| 64 | + let messageString = TWStringCreateWithNSString(message) | |
| 65 | + defer { | |
| 66 | + TWStringDelete(messageString) | |
| 67 | + } | |
| 68 | + return TWStringNSString(TWEthereumMessageSignerSignMessageImmutableX(privateKey.rawValue, messageString)) | |
| 69 | + } | |
| 70 | + | |
| 71 | + /// Sign a message with Eip-155 msg type. | |
| 72 | + /// | |
| 73 | + /// - Parameter privateKey:: the private key used for signing | |
| 74 | + /// - Parameter message:: A custom message which is input to the signing. | |
| 75 | + /// - Parameter chainId:: chainId for eip-155 protection | |
| 76 | + /// - Returns:s the signature, Hex-encoded. On invalid input empty string is returned. Returned object needs to be deleted after use. | |
| 77 | + public static func signMessageEip155(privateKey: PrivateKey, message: String, chainId: Int32) -> String { | |
| 78 | + let messageString = TWStringCreateWithNSString(message) | |
| 79 | + defer { | |
| 80 | + TWStringDelete(messageString) | |
| 81 | + } | |
| 82 | + return TWStringNSString(TWEthereumMessageSignerSignMessageEip155(privateKey.rawValue, messageString, Int32(chainId))) | |
| 83 | + } | |
| 84 | + | |
| 85 | + /// Verify signature for a message. | |
| 86 | + /// | |
| 87 | + /// - Parameter pubKey:: pubKey that will verify and recover the message from the signature | |
| 88 | + /// - Parameter message:: the message signed (without prefix) | |
| 89 | + /// - Parameter signature:: in Hex-encoded form. | |
| 90 | + /// - Returns:s false on any invalid input (does not throw), true if the message can be recovered from the signature | |
| 91 | + public static func verifyMessage(pubKey: PublicKey, message: String, signature: String) -> Bool { | |
| 92 | + let messageString = TWStringCreateWithNSString(message) | |
| 93 | + defer { | |
| 94 | + TWStringDelete(messageString) | |
| 95 | + } | |
| 96 | + let signatureString = TWStringCreateWithNSString(signature) | |
| 97 | + defer { | |
| 98 | + TWStringDelete(signatureString) | |
| 99 | + } | |
| 100 | + return TWEthereumMessageSignerVerifyMessage(pubKey.rawValue, messageString, signatureString) | |
| 101 | + } | |
| 102 | + | |
| 103 | + | |
| 104 | + init() { | |
| 105 | + } | |
| 106 | + | |
| 107 | + | |
| 108 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/EthereumRlp.swift
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public struct EthereumRlp { | |
| 14 | + | |
| 15 | + /// Encode an item or a list of items as Eth RLP binary format. | |
| 16 | + /// | |
| 17 | + /// - Parameter coin: EVM-compatible coin type. | |
| 18 | + /// - Parameter input: Non-null serialized `EthereumRlp::Proto::EncodingInput`. | |
| 19 | + /// - Returns: serialized `EthereumRlp::Proto::EncodingOutput`. | |
| 20 | + public static func encode(coin: CoinType, input: Data) -> Data { | |
| 21 | + let inputData = TWDataCreateWithNSData(input) | |
| 22 | + defer { | |
| 23 | + TWDataDelete(inputData) | |
| 24 | + } | |
| 25 | + return TWDataNSData(TWEthereumRlpEncode(TWCoinType(rawValue: coin.rawValue), inputData)) | |
| 26 | + } | |
| 27 | + | |
| 28 | + | |
| 29 | + init() { | |
| 30 | + } | |
| 31 | + | |
| 32 | + | |
| 33 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/FIOAccount.swift
+44 −0
@@ -0,0 +1,44 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a FIO Account name | |
| 13 | +public final class FIOAccount { | |
| 14 | + | |
| 15 | + /// Returns the short account string representation. | |
| 16 | + /// | |
| 17 | + /// - Parameter account: Pointer to a non-null FIO Account | |
| 18 | + /// - Returns: Account non-null string representation | |
| 19 | + public var description: String { | |
| 20 | + return TWStringNSString(TWFIOAccountDescription(rawValue)) | |
| 21 | + } | |
| 22 | + | |
| 23 | + let rawValue: OpaquePointer | |
| 24 | + | |
| 25 | + init(rawValue: OpaquePointer) { | |
| 26 | + self.rawValue = rawValue | |
| 27 | + } | |
| 28 | + | |
| 29 | + public init?(string: String) { | |
| 30 | + let stringString = TWStringCreateWithNSString(string) | |
| 31 | + defer { | |
| 32 | + TWStringDelete(stringString) | |
| 33 | + } | |
| 34 | + guard let rawValue = TWFIOAccountCreateWithString(stringString) else { | |
| 35 | + return nil | |
| 36 | + } | |
| 37 | + self.rawValue = rawValue | |
| 38 | + } | |
| 39 | + | |
| 40 | + deinit { | |
| 41 | + TWFIOAccountDelete(rawValue) | |
| 42 | + } | |
| 43 | + | |
| 44 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/FilecoinAddressConverter.swift
+44 −0
@@ -0,0 +1,44 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Filecoin-Ethereum address converter. | |
| 13 | +public struct FilecoinAddressConverter { | |
| 14 | + | |
| 15 | + /// Converts a Filecoin address to Ethereum. | |
| 16 | + /// | |
| 17 | + /// - Parameter filecoinAddress:: a Filecoin address. | |
| 18 | + /// - Returns:s the Ethereum address. On invalid input empty string is returned. Returned object needs to be deleted after use. | |
| 19 | + public static func convertToEthereum(filecoinAddress: String) -> String { | |
| 20 | + let filecoinAddressString = TWStringCreateWithNSString(filecoinAddress) | |
| 21 | + defer { | |
| 22 | + TWStringDelete(filecoinAddressString) | |
| 23 | + } | |
| 24 | + return TWStringNSString(TWFilecoinAddressConverterConvertToEthereum(filecoinAddressString)) | |
| 25 | + } | |
| 26 | + | |
| 27 | + /// Converts an Ethereum address to Filecoin. | |
| 28 | + /// | |
| 29 | + /// - Parameter ethAddress:: an Ethereum address. | |
| 30 | + /// - Returns:s the Filecoin address. On invalid input empty string is returned. Returned object needs to be deleted after use. | |
| 31 | + public static func convertFromEthereum(ethAddress: String) -> String { | |
| 32 | + let ethAddressString = TWStringCreateWithNSString(ethAddress) | |
| 33 | + defer { | |
| 34 | + TWStringDelete(ethAddressString) | |
| 35 | + } | |
| 36 | + return TWStringNSString(TWFilecoinAddressConverterConvertFromEthereum(ethAddressString)) | |
| 37 | + } | |
| 38 | + | |
| 39 | + | |
| 40 | + init() { | |
| 41 | + } | |
| 42 | + | |
| 43 | + | |
| 44 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/GroestlcoinAddress.swift
+69 −0
@@ -0,0 +1,69 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a legacy Groestlcoin address. | |
| 13 | +public final class GroestlcoinAddress: Address { | |
| 14 | + | |
| 15 | + /// Compares two addresses for equality. | |
| 16 | + /// | |
| 17 | + /// - Parameter lhs: left Non-null GroestlCoin address to be compared | |
| 18 | + /// - Parameter rhs: right Non-null GroestlCoin address to be compared | |
| 19 | + /// - Returns: true if both address are equal, false otherwise | |
| 20 | + public static func == (lhs: GroestlcoinAddress, rhs: GroestlcoinAddress) -> Bool { | |
| 21 | + return TWGroestlcoinAddressEqual(lhs.rawValue, rhs.rawValue) | |
| 22 | + } | |
| 23 | + | |
| 24 | + /// Determines if the string is a valid Groestlcoin address. | |
| 25 | + /// | |
| 26 | + /// - Parameter string: Non-null string. | |
| 27 | + /// - Returns: true if it's a valid address, false otherwise | |
| 28 | + public static func isValidString(string: String) -> Bool { | |
| 29 | + let stringString = TWStringCreateWithNSString(string) | |
| 30 | + defer { | |
| 31 | + TWStringDelete(stringString) | |
| 32 | + } | |
| 33 | + return TWGroestlcoinAddressIsValidString(stringString) | |
| 34 | + } | |
| 35 | + | |
| 36 | + /// Returns the address base58 string representation. | |
| 37 | + /// | |
| 38 | + /// - Parameter address: Non-null GroestlcoinAddress | |
| 39 | + /// - Returns: Address description as a non-null string | |
| 40 | + public var description: String { | |
| 41 | + return TWStringNSString(TWGroestlcoinAddressDescription(rawValue)) | |
| 42 | + } | |
| 43 | + | |
| 44 | + let rawValue: OpaquePointer | |
| 45 | + | |
| 46 | + init(rawValue: OpaquePointer) { | |
| 47 | + self.rawValue = rawValue | |
| 48 | + } | |
| 49 | + | |
| 50 | + public init?(string: String) { | |
| 51 | + let stringString = TWStringCreateWithNSString(string) | |
| 52 | + defer { | |
| 53 | + TWStringDelete(stringString) | |
| 54 | + } | |
| 55 | + guard let rawValue = TWGroestlcoinAddressCreateWithString(stringString) else { | |
| 56 | + return nil | |
| 57 | + } | |
| 58 | + self.rawValue = rawValue | |
| 59 | + } | |
| 60 | + | |
| 61 | + public init(publicKey: PublicKey, prefix: UInt8) { | |
| 62 | + rawValue = TWGroestlcoinAddressCreateWithPublicKey(publicKey.rawValue, prefix) | |
| 63 | + } | |
| 64 | + | |
| 65 | + deinit { | |
| 66 | + TWGroestlcoinAddressDelete(rawValue) | |
| 67 | + } | |
| 68 | + | |
| 69 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/HDVersion+Extension.swift
+25 −0
@@ -0,0 +1,25 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +extension HDVersion { | |
| 11 | + /// Determine if the HD Version is public | |
| 12 | + /// | |
| 13 | + /// - Parameter version: HD version | |
| 14 | + /// - Returns: true if the version is public, false otherwise | |
| 15 | + public var isPublic: Bool { | |
| 16 | + return TWHDVersionIsPublic(TWHDVersion(rawValue: rawValue)) | |
| 17 | + } | |
| 18 | + /// Determine if the HD Version is private | |
| 19 | + /// | |
| 20 | + /// - Parameter version: HD version | |
| 21 | + /// - Returns: true if the version is private, false otherwise | |
| 22 | + public var isPrivate: Bool { | |
| 23 | + return TWHDVersionIsPrivate(TWHDVersion(rawValue: rawValue)) | |
| 24 | + } | |
| 25 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/HDWallet.swift
+314 −0
@@ -0,0 +1,314 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Hierarchical Deterministic (HD) Wallet | |
| 13 | +public final class HDWallet { | |
| 14 | + | |
| 15 | + /// Computes the public key from an extended public key representation. | |
| 16 | + /// | |
| 17 | + /// - Parameter extended: extended public key | |
| 18 | + /// - Parameter coin: a coin type | |
| 19 | + /// - Parameter derivationPath: a derivation path | |
| 20 | + /// - Note: Returned object needs to be deleted with \TWPublicKeyDelete | |
| 21 | + /// - Returns: Nullable TWPublic key | |
| 22 | + public static func getPublicKeyFromExtended(extended: String, coin: CoinType, derivationPath: String) -> PublicKey? { | |
| 23 | + let extendedString = TWStringCreateWithNSString(extended) | |
| 24 | + defer { | |
| 25 | + TWStringDelete(extendedString) | |
| 26 | + } | |
| 27 | + let derivationPathString = TWStringCreateWithNSString(derivationPath) | |
| 28 | + defer { | |
| 29 | + TWStringDelete(derivationPathString) | |
| 30 | + } | |
| 31 | + guard let value = TWHDWalletGetPublicKeyFromExtended(extendedString, TWCoinType(rawValue: coin.rawValue), derivationPathString) else { | |
| 32 | + return nil | |
| 33 | + } | |
| 34 | + return PublicKey(rawValue: value) | |
| 35 | + } | |
| 36 | + | |
| 37 | + /// Wallet seed. | |
| 38 | + /// | |
| 39 | + /// - Parameter wallet: non-null TWHDWallet | |
| 40 | + /// - Returns: The wallet seed as a Non-null block of data. | |
| 41 | + public var seed: Data { | |
| 42 | + return TWDataNSData(TWHDWalletSeed(rawValue)) | |
| 43 | + } | |
| 44 | + | |
| 45 | + /// Wallet Mnemonic | |
| 46 | + /// | |
| 47 | + /// - Parameter wallet: non-null TWHDWallet | |
| 48 | + /// - Returns: The wallet mnemonic as a non-null TWString | |
| 49 | + public var mnemonic: String { | |
| 50 | + return TWStringNSString(TWHDWalletMnemonic(rawValue)) | |
| 51 | + } | |
| 52 | + | |
| 53 | + /// Wallet entropy | |
| 54 | + /// | |
| 55 | + /// - Parameter wallet: non-null TWHDWallet | |
| 56 | + /// - Returns: The wallet entropy as a non-null block of data. | |
| 57 | + public var entropy: Data { | |
| 58 | + return TWDataNSData(TWHDWalletEntropy(rawValue)) | |
| 59 | + } | |
| 60 | + | |
| 61 | + let rawValue: OpaquePointer | |
| 62 | + | |
| 63 | + init(rawValue: OpaquePointer) { | |
| 64 | + self.rawValue = rawValue | |
| 65 | + } | |
| 66 | + | |
| 67 | + public init?(strength: Int32, passphrase: String) { | |
| 68 | + let passphraseString = TWStringCreateWithNSString(passphrase) | |
| 69 | + defer { | |
| 70 | + TWStringDelete(passphraseString) | |
| 71 | + } | |
| 72 | + guard let rawValue = TWHDWalletCreate(Int32(strength), passphraseString) else { | |
| 73 | + return nil | |
| 74 | + } | |
| 75 | + self.rawValue = rawValue | |
| 76 | + } | |
| 77 | + | |
| 78 | + public init?(mnemonic: String, passphrase: String) { | |
| 79 | + let mnemonicString = TWStringCreateWithNSString(mnemonic) | |
| 80 | + defer { | |
| 81 | + TWStringDelete(mnemonicString) | |
| 82 | + } | |
| 83 | + let passphraseString = TWStringCreateWithNSString(passphrase) | |
| 84 | + defer { | |
| 85 | + TWStringDelete(passphraseString) | |
| 86 | + } | |
| 87 | + guard let rawValue = TWHDWalletCreateWithMnemonic(mnemonicString, passphraseString) else { | |
| 88 | + return nil | |
| 89 | + } | |
| 90 | + self.rawValue = rawValue | |
| 91 | + } | |
| 92 | + | |
| 93 | + public init?(mnemonic: String, passphrase: String, check: Bool) { | |
| 94 | + let mnemonicString = TWStringCreateWithNSString(mnemonic) | |
| 95 | + defer { | |
| 96 | + TWStringDelete(mnemonicString) | |
| 97 | + } | |
| 98 | + let passphraseString = TWStringCreateWithNSString(passphrase) | |
| 99 | + defer { | |
| 100 | + TWStringDelete(passphraseString) | |
| 101 | + } | |
| 102 | + guard let rawValue = TWHDWalletCreateWithMnemonicCheck(mnemonicString, passphraseString, check) else { | |
| 103 | + return nil | |
| 104 | + } | |
| 105 | + self.rawValue = rawValue | |
| 106 | + } | |
| 107 | + | |
| 108 | + public init?(entropy: Data, passphrase: String) { | |
| 109 | + let entropyData = TWDataCreateWithNSData(entropy) | |
| 110 | + defer { | |
| 111 | + TWDataDelete(entropyData) | |
| 112 | + } | |
| 113 | + let passphraseString = TWStringCreateWithNSString(passphrase) | |
| 114 | + defer { | |
| 115 | + TWStringDelete(passphraseString) | |
| 116 | + } | |
| 117 | + guard let rawValue = TWHDWalletCreateWithEntropy(entropyData, passphraseString) else { | |
| 118 | + return nil | |
| 119 | + } | |
| 120 | + self.rawValue = rawValue | |
| 121 | + } | |
| 122 | + | |
| 123 | + deinit { | |
| 124 | + TWHDWalletDelete(rawValue) | |
| 125 | + } | |
| 126 | + | |
| 127 | + /// Returns master key. | |
| 128 | + /// | |
| 129 | + /// - Parameter wallet: non-null TWHDWallet | |
| 130 | + /// - Parameter curve: a curve | |
| 131 | + /// - Note: Returned object needs to be deleted with \TWPrivateKeyDelete | |
| 132 | + /// - Returns: Non-null corresponding private key | |
| 133 | + public func getMasterKey(curve: Curve) -> PrivateKey { | |
| 134 | + return PrivateKey(rawValue: TWHDWalletGetMasterKey(rawValue, TWCurve(rawValue: curve.rawValue))) | |
| 135 | + } | |
| 136 | + | |
| 137 | + /// Generates the default private key for the specified coin, using default derivation. | |
| 138 | + /// | |
| 139 | + /// - SeeAlso: TWHDWalletGetKey | |
| 140 | + /// - SeeAlso: TWHDWalletGetKeyDerivation | |
| 141 | + /// - Parameter wallet: non-null TWHDWallet | |
| 142 | + /// - Parameter coin: a coin type | |
| 143 | + /// - Note: Returned object needs to be deleted with \TWPrivateKeyDelete | |
| 144 | + /// - Returns: return the default private key for the specified coin | |
| 145 | + public func getKeyForCoin(coin: CoinType) -> PrivateKey { | |
| 146 | + return PrivateKey(rawValue: TWHDWalletGetKeyForCoin(rawValue, TWCoinType(rawValue: coin.rawValue))) | |
| 147 | + } | |
| 148 | + | |
| 149 | + /// Generates the default address for the specified coin (without exposing intermediary private key), default derivation. | |
| 150 | + /// | |
| 151 | + /// - SeeAlso: TWHDWalletGetAddressDerivation | |
| 152 | + /// - Parameter wallet: non-null TWHDWallet | |
| 153 | + /// - Parameter coin: a coin type | |
| 154 | + /// - Returns: return the default address for the specified coin as a non-null TWString | |
| 155 | + public func getAddressForCoin(coin: CoinType) -> String { | |
| 156 | + return TWStringNSString(TWHDWalletGetAddressForCoin(rawValue, TWCoinType(rawValue: coin.rawValue))) | |
| 157 | + } | |
| 158 | + | |
| 159 | + /// Generates the default address for the specified coin and derivation (without exposing intermediary private key). | |
| 160 | + /// | |
| 161 | + /// - SeeAlso: TWHDWalletGetAddressForCoin | |
| 162 | + /// - Parameter wallet: non-null TWHDWallet | |
| 163 | + /// - Parameter coin: a coin type | |
| 164 | + /// - Parameter derivation: a (custom) derivation to use | |
| 165 | + /// - Returns: return the default address for the specified coin as a non-null TWString | |
| 166 | + public func getAddressDerivation(coin: CoinType, derivation: Derivation) -> String { | |
| 167 | + return TWStringNSString(TWHDWalletGetAddressDerivation(rawValue, TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue))) | |
| 168 | + } | |
| 169 | + | |
| 170 | + /// Generates the private key for the specified derivation path. | |
| 171 | + /// | |
| 172 | + /// - SeeAlso: TWHDWalletGetKeyForCoin | |
| 173 | + /// - SeeAlso: TWHDWalletGetKeyDerivation | |
| 174 | + /// - Parameter wallet: non-null TWHDWallet | |
| 175 | + /// - Parameter coin: a coin type | |
| 176 | + /// - Parameter derivationPath: a non-null derivation path | |
| 177 | + /// - Note: Returned object needs to be deleted with \TWPrivateKeyDelete | |
| 178 | + /// - Returns: The private key for the specified derivation path/coin, or null if the path is invalid | |
| 179 | + public func getKey(coin: CoinType, derivationPath: String) -> PrivateKey? { | |
| 180 | + let derivationPathString = TWStringCreateWithNSString(derivationPath) | |
| 181 | + defer { | |
| 182 | + TWStringDelete(derivationPathString) | |
| 183 | + } | |
| 184 | + guard let value = TWHDWalletGetKey(rawValue, TWCoinType(rawValue: coin.rawValue), derivationPathString) else { | |
| 185 | + return nil | |
| 186 | + } | |
| 187 | + return PrivateKey(rawValue: value) | |
| 188 | + } | |
| 189 | + | |
| 190 | + /// Generates the private key for the specified derivation. | |
| 191 | + /// | |
| 192 | + /// - SeeAlso: TWHDWalletGetKey | |
| 193 | + /// - SeeAlso: TWHDWalletGetKeyForCoin | |
| 194 | + /// - Parameter wallet: non-null TWHDWallet | |
| 195 | + /// - Parameter coin: a coin type | |
| 196 | + /// - Parameter derivation: a (custom) derivation to use | |
| 197 | + /// - Note: Returned object needs to be deleted with \TWPrivateKeyDelete | |
| 198 | + /// - Returns: The private key for the specified derivation path/coin | |
| 199 | + public func getKeyDerivation(coin: CoinType, derivation: Derivation) -> PrivateKey { | |
| 200 | + return PrivateKey(rawValue: TWHDWalletGetKeyDerivation(rawValue, TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue))) | |
| 201 | + } | |
| 202 | + | |
| 203 | + /// Generates the private key for the specified derivation path and curve. | |
| 204 | + /// | |
| 205 | + /// - Parameter wallet: non-null TWHDWallet | |
| 206 | + /// - Parameter curve: a curve | |
| 207 | + /// - Parameter derivationPath: a non-null derivation path | |
| 208 | + /// - Note: Returned object needs to be deleted with \TWPrivateKeyDelete | |
| 209 | + /// - Returns: The private key for the specified derivation path/curve, or null if the path is invalid | |
| 210 | + public func getKeyByCurve(curve: Curve, derivationPath: String) -> PrivateKey? { | |
| 211 | + let derivationPathString = TWStringCreateWithNSString(derivationPath) | |
| 212 | + defer { | |
| 213 | + TWStringDelete(derivationPathString) | |
| 214 | + } | |
| 215 | + guard let value = TWHDWalletGetKeyByCurve(rawValue, TWCurve(rawValue: curve.rawValue), derivationPathString) else { | |
| 216 | + return nil | |
| 217 | + } | |
| 218 | + return PrivateKey(rawValue: value) | |
| 219 | + } | |
| 220 | + | |
| 221 | + /// Shortcut method to generate private key with the specified account/change/address (bip44 standard). | |
| 222 | + /// | |
| 223 | + /// - SeeAlso: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki | |
| 224 | + /// | |
| 225 | + /// - Parameter wallet: non-null TWHDWallet | |
| 226 | + /// - Parameter coin: a coin type | |
| 227 | + /// - Parameter account: valid bip44 account | |
| 228 | + /// - Parameter change: valid bip44 change | |
| 229 | + /// - Parameter address: valid bip44 address | |
| 230 | + /// - Note: Returned object needs to be deleted with \TWPrivateKeyDelete | |
| 231 | + /// - Returns: The private key for the specified bip44 parameters | |
| 232 | + public func getDerivedKey(coin: CoinType, account: UInt32, change: UInt32, address: UInt32) -> PrivateKey { | |
| 233 | + return PrivateKey(rawValue: TWHDWalletGetDerivedKey(rawValue, TWCoinType(rawValue: coin.rawValue), account, change, address)) | |
| 234 | + } | |
| 235 | + | |
| 236 | + /// Returns the extended private key (for default 0 account). | |
| 237 | + /// | |
| 238 | + /// - Parameter wallet: non-null TWHDWallet | |
| 239 | + /// - Parameter purpose: a purpose | |
| 240 | + /// - Parameter coin: a coin type | |
| 241 | + /// - Parameter version: hd version | |
| 242 | + /// - Note: Returned object needs to be deleted with \TWStringDelete | |
| 243 | + /// - Returns: Extended private key as a non-null TWString | |
| 244 | + public func getExtendedPrivateKey(purpose: Purpose, coin: CoinType, version: HDVersion) -> String { | |
| 245 | + return TWStringNSString(TWHDWalletGetExtendedPrivateKey(rawValue, TWPurpose(rawValue: purpose.rawValue), TWCoinType(rawValue: coin.rawValue), TWHDVersion(rawValue: version.rawValue))) | |
| 246 | + } | |
| 247 | + | |
| 248 | + /// Returns the extended public key (for default 0 account). | |
| 249 | + /// | |
| 250 | + /// - Parameter wallet: non-null TWHDWallet | |
| 251 | + /// - Parameter purpose: a purpose | |
| 252 | + /// - Parameter coin: a coin type | |
| 253 | + /// - Parameter version: hd version | |
| 254 | + /// - Note: Returned object needs to be deleted with \TWStringDelete | |
| 255 | + /// - Returns: Extended public key as a non-null TWString | |
| 256 | + public func getExtendedPublicKey(purpose: Purpose, coin: CoinType, version: HDVersion) -> String { | |
| 257 | + return TWStringNSString(TWHDWalletGetExtendedPublicKey(rawValue, TWPurpose(rawValue: purpose.rawValue), TWCoinType(rawValue: coin.rawValue), TWHDVersion(rawValue: version.rawValue))) | |
| 258 | + } | |
| 259 | + | |
| 260 | + /// Returns the extended private key, for custom account. | |
| 261 | + /// | |
| 262 | + /// - Parameter wallet: non-null TWHDWallet | |
| 263 | + /// - Parameter purpose: a purpose | |
| 264 | + /// - Parameter coin: a coin type | |
| 265 | + /// - Parameter derivation: a derivation | |
| 266 | + /// - Parameter version: an hd version | |
| 267 | + /// - Parameter account: valid bip44 account | |
| 268 | + /// - Note: Returned object needs to be deleted with \TWStringDelete | |
| 269 | + /// - Returns: Extended private key as a non-null TWString | |
| 270 | + public func getExtendedPrivateKeyAccount(purpose: Purpose, coin: CoinType, derivation: Derivation, version: HDVersion, account: UInt32) -> String { | |
| 271 | + return TWStringNSString(TWHDWalletGetExtendedPrivateKeyAccount(rawValue, TWPurpose(rawValue: purpose.rawValue), TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue), TWHDVersion(rawValue: version.rawValue), account)) | |
| 272 | + } | |
| 273 | + | |
| 274 | + /// Returns the extended public key, for custom account. | |
| 275 | + /// | |
| 276 | + /// - Parameter wallet: non-null TWHDWallet | |
| 277 | + /// - Parameter purpose: a purpose | |
| 278 | + /// - Parameter coin: a coin type | |
| 279 | + /// - Parameter derivation: a derivation | |
| 280 | + /// - Parameter version: an hd version | |
| 281 | + /// - Parameter account: valid bip44 account | |
| 282 | + /// - Note: Returned object needs to be deleted with \TWStringDelete | |
| 283 | + /// - Returns: Extended public key as a non-null TWString | |
| 284 | + public func getExtendedPublicKeyAccount(purpose: Purpose, coin: CoinType, derivation: Derivation, version: HDVersion, account: UInt32) -> String { | |
| 285 | + return TWStringNSString(TWHDWalletGetExtendedPublicKeyAccount(rawValue, TWPurpose(rawValue: purpose.rawValue), TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue), TWHDVersion(rawValue: version.rawValue), account)) | |
| 286 | + } | |
| 287 | + | |
| 288 | + /// Returns the extended private key (for default 0 account with derivation). | |
| 289 | + /// | |
| 290 | + /// - Parameter wallet: non-null TWHDWallet | |
| 291 | + /// - Parameter purpose: a purpose | |
| 292 | + /// - Parameter coin: a coin type | |
| 293 | + /// - Parameter derivation: a derivation | |
| 294 | + /// - Parameter version: an hd version | |
| 295 | + /// - Note: Returned object needs to be deleted with \TWStringDelete | |
| 296 | + /// - Returns: Extended private key as a non-null TWString | |
| 297 | + public func getExtendedPrivateKeyDerivation(purpose: Purpose, coin: CoinType, derivation: Derivation, version: HDVersion) -> String { | |
| 298 | + return TWStringNSString(TWHDWalletGetExtendedPrivateKeyDerivation(rawValue, TWPurpose(rawValue: purpose.rawValue), TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue), TWHDVersion(rawValue: version.rawValue))) | |
| 299 | + } | |
| 300 | + | |
| 301 | + /// Returns the extended public key (for default 0 account with derivation). | |
| 302 | + /// | |
| 303 | + /// - Parameter wallet: non-null TWHDWallet | |
| 304 | + /// - Parameter purpose: a purpose | |
| 305 | + /// - Parameter coin: a coin type | |
| 306 | + /// - Parameter derivation: a derivation | |
| 307 | + /// - Parameter version: an hd version | |
| 308 | + /// - Note: Returned object needs to be deleted with \TWStringDelete | |
| 309 | + /// - Returns: Extended public key as a non-null TWString | |
| 310 | + public func getExtendedPublicKeyDerivation(purpose: Purpose, coin: CoinType, derivation: Derivation, version: HDVersion) -> String { | |
| 311 | + return TWStringNSString(TWHDWalletGetExtendedPublicKeyDerivation(rawValue, TWPurpose(rawValue: purpose.rawValue), TWCoinType(rawValue: coin.rawValue), TWDerivation(rawValue: derivation.rawValue), TWHDVersion(rawValue: version.rawValue))) | |
| 312 | + } | |
| 313 | + | |
| 314 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Hash.swift
+249 −0
@@ -0,0 +1,249 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Hash functions | |
| 13 | +public struct Hash { | |
| 14 | + | |
| 15 | + /// Computes the SHA1 of a block of data. | |
| 16 | + /// | |
| 17 | + /// - Parameter data: Non-null block of data | |
| 18 | + /// - Returns: Non-null computed SHA1 block of data | |
| 19 | + public static func sha1(data: Data) -> Data { | |
| 20 | + let dataData = TWDataCreateWithNSData(data) | |
| 21 | + defer { | |
| 22 | + TWDataDelete(dataData) | |
| 23 | + } | |
| 24 | + return TWDataNSData(TWHashSHA1(dataData)) | |
| 25 | + } | |
| 26 | + | |
| 27 | + /// Computes the SHA256 of a block of data. | |
| 28 | + /// | |
| 29 | + /// - Parameter data: Non-null block of data | |
| 30 | + /// - Returns: Non-null computed SHA256 block of data | |
| 31 | + public static func sha256(data: Data) -> Data { | |
| 32 | + let dataData = TWDataCreateWithNSData(data) | |
| 33 | + defer { | |
| 34 | + TWDataDelete(dataData) | |
| 35 | + } | |
| 36 | + return TWDataNSData(TWHashSHA256(dataData)) | |
| 37 | + } | |
| 38 | + | |
| 39 | + /// Computes the SHA512 of a block of data. | |
| 40 | + /// | |
| 41 | + /// - Parameter data: Non-null block of data | |
| 42 | + /// - Returns: Non-null computed SHA512 block of data | |
| 43 | + public static func sha512(data: Data) -> Data { | |
| 44 | + let dataData = TWDataCreateWithNSData(data) | |
| 45 | + defer { | |
| 46 | + TWDataDelete(dataData) | |
| 47 | + } | |
| 48 | + return TWDataNSData(TWHashSHA512(dataData)) | |
| 49 | + } | |
| 50 | + | |
| 51 | + /// Computes the SHA512_256 of a block of data. | |
| 52 | + /// | |
| 53 | + /// - Parameter data: Non-null block of data | |
| 54 | + /// - Returns: Non-null computed SHA512_256 block of data | |
| 55 | + public static func sha512_256(data: Data) -> Data { | |
| 56 | + let dataData = TWDataCreateWithNSData(data) | |
| 57 | + defer { | |
| 58 | + TWDataDelete(dataData) | |
| 59 | + } | |
| 60 | + return TWDataNSData(TWHashSHA512_256(dataData)) | |
| 61 | + } | |
| 62 | + | |
| 63 | + /// Computes the Keccak256 of a block of data. | |
| 64 | + /// | |
| 65 | + /// - Parameter data: Non-null block of data | |
| 66 | + /// - Returns: Non-null computed Keccak256 block of data | |
| 67 | + public static func keccak256(data: Data) -> Data { | |
| 68 | + let dataData = TWDataCreateWithNSData(data) | |
| 69 | + defer { | |
| 70 | + TWDataDelete(dataData) | |
| 71 | + } | |
| 72 | + return TWDataNSData(TWHashKeccak256(dataData)) | |
| 73 | + } | |
| 74 | + | |
| 75 | + /// Computes the Keccak512 of a block of data. | |
| 76 | + /// | |
| 77 | + /// - Parameter data: Non-null block of data | |
| 78 | + /// - Returns: Non-null computed Keccak512 block of data | |
| 79 | + public static func keccak512(data: Data) -> Data { | |
| 80 | + let dataData = TWDataCreateWithNSData(data) | |
| 81 | + defer { | |
| 82 | + TWDataDelete(dataData) | |
| 83 | + } | |
| 84 | + return TWDataNSData(TWHashKeccak512(dataData)) | |
| 85 | + } | |
| 86 | + | |
| 87 | + /// Computes the SHA3_256 of a block of data. | |
| 88 | + /// | |
| 89 | + /// - Parameter data: Non-null block of data | |
| 90 | + /// - Returns: Non-null computed SHA3_256 block of data | |
| 91 | + public static func sha3_256(data: Data) -> Data { | |
| 92 | + let dataData = TWDataCreateWithNSData(data) | |
| 93 | + defer { | |
| 94 | + TWDataDelete(dataData) | |
| 95 | + } | |
| 96 | + return TWDataNSData(TWHashSHA3_256(dataData)) | |
| 97 | + } | |
| 98 | + | |
| 99 | + /// Computes the SHA3_512 of a block of data. | |
| 100 | + /// | |
| 101 | + /// - Parameter data: Non-null block of data | |
| 102 | + /// - Returns: Non-null computed SHA3_512 block of data | |
| 103 | + public static func sha3_512(data: Data) -> Data { | |
| 104 | + let dataData = TWDataCreateWithNSData(data) | |
| 105 | + defer { | |
| 106 | + TWDataDelete(dataData) | |
| 107 | + } | |
| 108 | + return TWDataNSData(TWHashSHA3_512(dataData)) | |
| 109 | + } | |
| 110 | + | |
| 111 | + /// Computes the RIPEMD of a block of data. | |
| 112 | + /// | |
| 113 | + /// - Parameter data: Non-null block of data | |
| 114 | + /// - Returns: Non-null computed RIPEMD block of data | |
| 115 | + public static func ripemd(data: Data) -> Data { | |
| 116 | + let dataData = TWDataCreateWithNSData(data) | |
| 117 | + defer { | |
| 118 | + TWDataDelete(dataData) | |
| 119 | + } | |
| 120 | + return TWDataNSData(TWHashRIPEMD(dataData)) | |
| 121 | + } | |
| 122 | + | |
| 123 | + /// Computes the Blake256 of a block of data. | |
| 124 | + /// | |
| 125 | + /// - Parameter data: Non-null block of data | |
| 126 | + /// - Returns: Non-null computed Blake256 block of data | |
| 127 | + public static func blake256(data: Data) -> Data { | |
| 128 | + let dataData = TWDataCreateWithNSData(data) | |
| 129 | + defer { | |
| 130 | + TWDataDelete(dataData) | |
| 131 | + } | |
| 132 | + return TWDataNSData(TWHashBlake256(dataData)) | |
| 133 | + } | |
| 134 | + | |
| 135 | + /// Computes the Blake2b of a block of data. | |
| 136 | + /// | |
| 137 | + /// - Parameter data: Non-null block of data | |
| 138 | + /// - Returns: Non-null computed Blake2b block of data | |
| 139 | + public static func blake2b(data: Data, size: Int) -> Data { | |
| 140 | + let dataData = TWDataCreateWithNSData(data) | |
| 141 | + defer { | |
| 142 | + TWDataDelete(dataData) | |
| 143 | + } | |
| 144 | + return TWDataNSData(TWHashBlake2b(dataData, size)) | |
| 145 | + } | |
| 146 | + | |
| 147 | + /// Computes the Groestl512 of a block of data. | |
| 148 | + /// | |
| 149 | + /// - Parameter data: Non-null block of data | |
| 150 | + /// - Returns: Non-null computed Groestl512 block of data | |
| 151 | + public static func blake2bPersonal(data: Data, personal: Data, outlen: Int) -> Data { | |
| 152 | + let dataData = TWDataCreateWithNSData(data) | |
| 153 | + defer { | |
| 154 | + TWDataDelete(dataData) | |
| 155 | + } | |
| 156 | + let personalData = TWDataCreateWithNSData(personal) | |
| 157 | + defer { | |
| 158 | + TWDataDelete(personalData) | |
| 159 | + } | |
| 160 | + return TWDataNSData(TWHashBlake2bPersonal(dataData, personalData, outlen)) | |
| 161 | + } | |
| 162 | + | |
| 163 | + | |
| 164 | + public static func groestl512(data: Data) -> Data { | |
| 165 | + let dataData = TWDataCreateWithNSData(data) | |
| 166 | + defer { | |
| 167 | + TWDataDelete(dataData) | |
| 168 | + } | |
| 169 | + return TWDataNSData(TWHashGroestl512(dataData)) | |
| 170 | + } | |
| 171 | + | |
| 172 | + /// Computes the SHA256D of a block of data. | |
| 173 | + /// | |
| 174 | + /// - Parameter data: Non-null block of data | |
| 175 | + /// - Returns: Non-null computed SHA256D block of data | |
| 176 | + public static func sha256SHA256(data: Data) -> Data { | |
| 177 | + let dataData = TWDataCreateWithNSData(data) | |
| 178 | + defer { | |
| 179 | + TWDataDelete(dataData) | |
| 180 | + } | |
| 181 | + return TWDataNSData(TWHashSHA256SHA256(dataData)) | |
| 182 | + } | |
| 183 | + | |
| 184 | + /// Computes the SHA256RIPEMD of a block of data. | |
| 185 | + /// | |
| 186 | + /// - Parameter data: Non-null block of data | |
| 187 | + /// - Returns: Non-null computed SHA256RIPEMD block of data | |
| 188 | + public static func sha256RIPEMD(data: Data) -> Data { | |
| 189 | + let dataData = TWDataCreateWithNSData(data) | |
| 190 | + defer { | |
| 191 | + TWDataDelete(dataData) | |
| 192 | + } | |
| 193 | + return TWDataNSData(TWHashSHA256RIPEMD(dataData)) | |
| 194 | + } | |
| 195 | + | |
| 196 | + /// Computes the SHA3_256RIPEMD of a block of data. | |
| 197 | + /// | |
| 198 | + /// - Parameter data: Non-null block of data | |
| 199 | + /// - Returns: Non-null computed SHA3_256RIPEMD block of data | |
| 200 | + public static func sha3_256RIPEMD(data: Data) -> Data { | |
| 201 | + let dataData = TWDataCreateWithNSData(data) | |
| 202 | + defer { | |
| 203 | + TWDataDelete(dataData) | |
| 204 | + } | |
| 205 | + return TWDataNSData(TWHashSHA3_256RIPEMD(dataData)) | |
| 206 | + } | |
| 207 | + | |
| 208 | + /// Computes the Blake256D of a block of data. | |
| 209 | + /// | |
| 210 | + /// - Parameter data: Non-null block of data | |
| 211 | + /// - Returns: Non-null computed Blake256D block of data | |
| 212 | + public static func blake256Blake256(data: Data) -> Data { | |
| 213 | + let dataData = TWDataCreateWithNSData(data) | |
| 214 | + defer { | |
| 215 | + TWDataDelete(dataData) | |
| 216 | + } | |
| 217 | + return TWDataNSData(TWHashBlake256Blake256(dataData)) | |
| 218 | + } | |
| 219 | + | |
| 220 | + /// Computes the Blake256RIPEMD of a block of data. | |
| 221 | + /// | |
| 222 | + /// - Parameter data: Non-null block of data | |
| 223 | + /// - Returns: Non-null computed Blake256RIPEMD block of data | |
| 224 | + public static func blake256RIPEMD(data: Data) -> Data { | |
| 225 | + let dataData = TWDataCreateWithNSData(data) | |
| 226 | + defer { | |
| 227 | + TWDataDelete(dataData) | |
| 228 | + } | |
| 229 | + return TWDataNSData(TWHashBlake256RIPEMD(dataData)) | |
| 230 | + } | |
| 231 | + | |
| 232 | + /// Computes the Groestl512D of a block of data. | |
| 233 | + /// | |
| 234 | + /// - Parameter data: Non-null block of data | |
| 235 | + /// - Returns: Non-null computed Groestl512D block of data | |
| 236 | + public static func groestl512Groestl512(data: Data) -> Data { | |
| 237 | + let dataData = TWDataCreateWithNSData(data) | |
| 238 | + defer { | |
| 239 | + TWDataDelete(dataData) | |
| 240 | + } | |
| 241 | + return TWDataNSData(TWHashGroestl512Groestl512(dataData)) | |
| 242 | + } | |
| 243 | + | |
| 244 | + | |
| 245 | + init() { | |
| 246 | + } | |
| 247 | + | |
| 248 | + | |
| 249 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/LiquidStaking.swift
+32 −0
@@ -0,0 +1,32 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// THORChain swap functions | |
| 13 | +public struct LiquidStaking { | |
| 14 | + | |
| 15 | + /// Builds a LiquidStaking transaction input. | |
| 16 | + /// | |
| 17 | + /// - Parameter input: The serialized data of LiquidStakingInput. | |
| 18 | + /// - Returns: The serialized data of LiquidStakingOutput. | |
| 19 | + public static func buildRequest(input: Data) -> Data { | |
| 20 | + let inputData = TWDataCreateWithNSData(input) | |
| 21 | + defer { | |
| 22 | + TWDataDelete(inputData) | |
| 23 | + } | |
| 24 | + return TWDataNSData(TWLiquidStakingBuildRequest(inputData)) | |
| 25 | + } | |
| 26 | + | |
| 27 | + | |
| 28 | + init() { | |
| 29 | + } | |
| 30 | + | |
| 31 | + | |
| 32 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/MessageSigner.swift
+67 −0
@@ -0,0 +1,67 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | + | |
| 13 | +public final class MessageSigner { | |
| 14 | + | |
| 15 | + /// Signs an arbitrary message to prove ownership of an address for off-chain services. | |
| 16 | + /// | |
| 17 | + /// - Parameter coin: The given coin type to sign the message for. | |
| 18 | + /// - Parameter input: The serialized data of a signing input (e.g. TW.Ethereum.Proto.MessageSigningInput). | |
| 19 | + /// - Returns: The serialized data of a `SigningOutput` proto object. (e.g. TW.Ethereum.Proto.MessageSigningOutput). | |
| 20 | + public static func sign(coin: CoinType, input: Data) -> Data? { | |
| 21 | + let inputData = TWDataCreateWithNSData(input) | |
| 22 | + defer { | |
| 23 | + TWDataDelete(inputData) | |
| 24 | + } | |
| 25 | + guard let result = TWMessageSignerSign(TWCoinType(rawValue: coin.rawValue), inputData) else { | |
| 26 | + return nil | |
| 27 | + } | |
| 28 | + return TWDataNSData(result) | |
| 29 | + } | |
| 30 | + | |
| 31 | + /// Verifies a signature for a message. | |
| 32 | + /// | |
| 33 | + /// - Parameter coin: The given coin type to sign the message for. | |
| 34 | + /// - Parameter input: The serialized data of a verifying input (e.g. TW.Ethereum.Proto.MessageVerifyingInput). | |
| 35 | + /// - Returns: whether the signature is valid. | |
| 36 | + public static func verify(coin: CoinType, input: Data) -> Bool { | |
| 37 | + let inputData = TWDataCreateWithNSData(input) | |
| 38 | + defer { | |
| 39 | + TWDataDelete(inputData) | |
| 40 | + } | |
| 41 | + return TWMessageSignerVerify(TWCoinType(rawValue: coin.rawValue), inputData) | |
| 42 | + } | |
| 43 | + | |
| 44 | + /// Computes preimage hashes of a message. | |
| 45 | + /// | |
| 46 | + /// - Parameter coin: The given coin type to sign the message for. | |
| 47 | + /// - Parameter input: The serialized data of a signing input (e.g. TW.Ethereum.Proto.MessageSigningInput). | |
| 48 | + /// - Returns: The serialized data of TW.TxCompiler.PreSigningOutput. | |
| 49 | + public static func preImageHashes(coin: CoinType, input: Data) -> Data? { | |
| 50 | + let inputData = TWDataCreateWithNSData(input) | |
| 51 | + defer { | |
| 52 | + TWDataDelete(inputData) | |
| 53 | + } | |
| 54 | + guard let result = TWMessageSignerPreImageHashes(TWCoinType(rawValue: coin.rawValue), inputData) else { | |
| 55 | + return nil | |
| 56 | + } | |
| 57 | + return TWDataNSData(result) | |
| 58 | + } | |
| 59 | + | |
| 60 | + let rawValue: OpaquePointer | |
| 61 | + | |
| 62 | + init(rawValue: OpaquePointer) { | |
| 63 | + self.rawValue = rawValue | |
| 64 | + } | |
| 65 | + | |
| 66 | + | |
| 67 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Mnemonic.swift
+56 −0
@@ -0,0 +1,56 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Mnemonic validate / lookup functions | |
| 13 | +public struct Mnemonic { | |
| 14 | + | |
| 15 | + /// Determines whether a BIP39 English mnemonic phrase is valid. | |
| 16 | + /// | |
| 17 | + /// - Parameter mnemonic: Non-null BIP39 english mnemonic | |
| 18 | + /// - Returns: true if the mnemonic is valid, false otherwise | |
| 19 | + public static func isValid(mnemonic: String) -> Bool { | |
| 20 | + let mnemonicString = TWStringCreateWithNSString(mnemonic) | |
| 21 | + defer { | |
| 22 | + TWStringDelete(mnemonicString) | |
| 23 | + } | |
| 24 | + return TWMnemonicIsValid(mnemonicString) | |
| 25 | + } | |
| 26 | + | |
| 27 | + /// Determines whether word is a valid BIP39 English mnemonic word. | |
| 28 | + /// | |
| 29 | + /// - Parameter word: Non-null BIP39 English mnemonic word | |
| 30 | + /// - Returns: true if the word is a valid BIP39 English mnemonic word, false otherwise | |
| 31 | + public static func isValidWord(word: String) -> Bool { | |
| 32 | + let wordString = TWStringCreateWithNSString(word) | |
| 33 | + defer { | |
| 34 | + TWStringDelete(wordString) | |
| 35 | + } | |
| 36 | + return TWMnemonicIsValidWord(wordString) | |
| 37 | + } | |
| 38 | + | |
| 39 | + /// Return BIP39 English words that match the given prefix. A single string is returned, with space-separated list of words. | |
| 40 | + /// | |
| 41 | + /// - Parameter prefix: Non-null string prefix | |
| 42 | + /// - Returns: Single non-null string, space-separated list of words containing BIP39 words that match the given prefix. | |
| 43 | + public static func suggest(prefix: String) -> String { | |
| 44 | + let prefixString = TWStringCreateWithNSString(prefix) | |
| 45 | + defer { | |
| 46 | + TWStringDelete(prefixString) | |
| 47 | + } | |
| 48 | + return TWStringNSString(TWMnemonicSuggest(prefixString)) | |
| 49 | + } | |
| 50 | + | |
| 51 | + | |
| 52 | + init() { | |
| 53 | + } | |
| 54 | + | |
| 55 | + | |
| 56 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/NEARAccount.swift
+44 −0
@@ -0,0 +1,44 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a NEAR Account name | |
| 13 | +public final class NEARAccount { | |
| 14 | + | |
| 15 | + /// Returns the user friendly string representation. | |
| 16 | + /// | |
| 17 | + /// - Parameter account: Pointer to a non-null NEAR Account | |
| 18 | + /// - Returns: Non-null string account description | |
| 19 | + public var description: String { | |
| 20 | + return TWStringNSString(TWNEARAccountDescription(rawValue)) | |
| 21 | + } | |
| 22 | + | |
| 23 | + let rawValue: OpaquePointer | |
| 24 | + | |
| 25 | + init(rawValue: OpaquePointer) { | |
| 26 | + self.rawValue = rawValue | |
| 27 | + } | |
| 28 | + | |
| 29 | + public init?(string: String) { | |
| 30 | + let stringString = TWStringCreateWithNSString(string) | |
| 31 | + defer { | |
| 32 | + TWStringDelete(stringString) | |
| 33 | + } | |
| 34 | + guard let rawValue = TWNEARAccountCreateWithString(stringString) else { | |
| 35 | + return nil | |
| 36 | + } | |
| 37 | + self.rawValue = rawValue | |
| 38 | + } | |
| 39 | + | |
| 40 | + deinit { | |
| 41 | + TWNEARAccountDelete(rawValue) | |
| 42 | + } | |
| 43 | + | |
| 44 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/NervosAddress.swift
+85 −0
@@ -0,0 +1,85 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a Nervos address. | |
| 13 | +public final class NervosAddress: Address { | |
| 14 | + | |
| 15 | + /// Compares two addresses for equality. | |
| 16 | + /// | |
| 17 | + /// - Parameter lhs: The first address to compare. | |
| 18 | + /// - Parameter rhs: The second address to compare. | |
| 19 | + /// - Returns: bool indicating the addresses are equal. | |
| 20 | + public static func == (lhs: NervosAddress, rhs: NervosAddress) -> Bool { | |
| 21 | + return TWNervosAddressEqual(lhs.rawValue, rhs.rawValue) | |
| 22 | + } | |
| 23 | + | |
| 24 | + /// Determines if the string is a valid Nervos address. | |
| 25 | + /// | |
| 26 | + /// - Parameter string: string to validate. | |
| 27 | + /// - Returns: bool indicating if the address is valid. | |
| 28 | + public static func isValidString(string: String) -> Bool { | |
| 29 | + let stringString = TWStringCreateWithNSString(string) | |
| 30 | + defer { | |
| 31 | + TWStringDelete(stringString) | |
| 32 | + } | |
| 33 | + return TWNervosAddressIsValidString(stringString) | |
| 34 | + } | |
| 35 | + | |
| 36 | + /// Returns the address string representation. | |
| 37 | + /// | |
| 38 | + /// - Parameter address: Address to get the string representation of. | |
| 39 | + public var description: String { | |
| 40 | + return TWStringNSString(TWNervosAddressDescription(rawValue)) | |
| 41 | + } | |
| 42 | + | |
| 43 | + /// Returns the Code hash | |
| 44 | + /// | |
| 45 | + /// - Parameter address: Address to get the keyhash data of. | |
| 46 | + public var codeHash: Data { | |
| 47 | + return TWDataNSData(TWNervosAddressCodeHash(rawValue)) | |
| 48 | + } | |
| 49 | + | |
| 50 | + /// Returns the address hash type | |
| 51 | + /// | |
| 52 | + /// - Parameter address: Address to get the hash type of. | |
| 53 | + public var hashType: String { | |
| 54 | + return TWStringNSString(TWNervosAddressHashType(rawValue)) | |
| 55 | + } | |
| 56 | + | |
| 57 | + /// Returns the address args data. | |
| 58 | + /// | |
| 59 | + /// - Parameter address: Address to get the args data of. | |
| 60 | + public var args: Data { | |
| 61 | + return TWDataNSData(TWNervosAddressArgs(rawValue)) | |
| 62 | + } | |
| 63 | + | |
| 64 | + let rawValue: OpaquePointer | |
| 65 | + | |
| 66 | + init(rawValue: OpaquePointer) { | |
| 67 | + self.rawValue = rawValue | |
| 68 | + } | |
| 69 | + | |
| 70 | + public init?(string: String) { | |
| 71 | + let stringString = TWStringCreateWithNSString(string) | |
| 72 | + defer { | |
| 73 | + TWStringDelete(stringString) | |
| 74 | + } | |
| 75 | + guard let rawValue = TWNervosAddressCreateWithString(stringString) else { | |
| 76 | + return nil | |
| 77 | + } | |
| 78 | + self.rawValue = rawValue | |
| 79 | + } | |
| 80 | + | |
| 81 | + deinit { | |
| 82 | + TWNervosAddressDelete(rawValue) | |
| 83 | + } | |
| 84 | + | |
| 85 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/PBKDF2.swift
+64 −0
@@ -0,0 +1,64 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Password-Based Key Derivation Function 2 | |
| 13 | +public struct PBKDF2 { | |
| 14 | + | |
| 15 | + /// Derives a key from a password and a salt using PBKDF2 + Sha256. | |
| 16 | + /// | |
| 17 | + /// - Parameter password: is the master password from which a derived key is generated | |
| 18 | + /// - Parameter salt: is a sequence of bits, known as a cryptographic salt | |
| 19 | + /// - Parameter iterations: is the number of iterations desired | |
| 20 | + /// - Parameter dkLen: is the desired bit-length of the derived key | |
| 21 | + /// - Returns: the derived key data. | |
| 22 | + public static func hmacSha256(password: Data, salt: Data, iterations: UInt32, dkLen: UInt32) -> Data? { | |
| 23 | + let passwordData = TWDataCreateWithNSData(password) | |
| 24 | + defer { | |
| 25 | + TWDataDelete(passwordData) | |
| 26 | + } | |
| 27 | + let saltData = TWDataCreateWithNSData(salt) | |
| 28 | + defer { | |
| 29 | + TWDataDelete(saltData) | |
| 30 | + } | |
| 31 | + guard let result = TWPBKDF2HmacSha256(passwordData, saltData, iterations, dkLen) else { | |
| 32 | + return nil | |
| 33 | + } | |
| 34 | + return TWDataNSData(result) | |
| 35 | + } | |
| 36 | + | |
| 37 | + /// Derives a key from a password and a salt using PBKDF2 + Sha512. | |
| 38 | + /// | |
| 39 | + /// - Parameter password: is the master password from which a derived key is generated | |
| 40 | + /// - Parameter salt: is a sequence of bits, known as a cryptographic salt | |
| 41 | + /// - Parameter iterations: is the number of iterations desired | |
| 42 | + /// - Parameter dkLen: is the desired bit-length of the derived key | |
| 43 | + /// - Returns: the derived key data. | |
| 44 | + public static func hmacSha512(password: Data, salt: Data, iterations: UInt32, dkLen: UInt32) -> Data? { | |
| 45 | + let passwordData = TWDataCreateWithNSData(password) | |
| 46 | + defer { | |
| 47 | + TWDataDelete(passwordData) | |
| 48 | + } | |
| 49 | + let saltData = TWDataCreateWithNSData(salt) | |
| 50 | + defer { | |
| 51 | + TWDataDelete(saltData) | |
| 52 | + } | |
| 53 | + guard let result = TWPBKDF2HmacSha512(passwordData, saltData, iterations, dkLen) else { | |
| 54 | + return nil | |
| 55 | + } | |
| 56 | + return TWDataNSData(result) | |
| 57 | + } | |
| 58 | + | |
| 59 | + | |
| 60 | + init() { | |
| 61 | + } | |
| 62 | + | |
| 63 | + | |
| 64 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/PrivateKey.swift
+184 −0
@@ -0,0 +1,184 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | +// | |
| 7 | +// This is a GENERATED FILE, changes made here WILL BE LOST. | |
| 8 | +// | |
| 9 | + | |
| 10 | +import Foundation | |
| 11 | + | |
| 12 | +/// Represents a private key. | |
| 13 | +public final class PrivateKey { | |
| 14 | + | |
| 15 | + /// Determines if the given private key is valid or not. | |
| 16 | + /// | |
| 17 | + /// - Parameter data: block of data (private key bytes) | |
| 18 | + /// - Parameter curve: Eliptic curve of the private key | |
| 19 | + /// - Returns: true if the private key is valid, false otherwise | |
| 20 | + public static func isValid(data: Data, curve: Curve) -> Bool { | |
| 21 | + let dataData = TWDataCreateWithNSData(data) | |
| 22 | + defer { | |
| 23 | + TWDataDelete(dataData) | |
| 24 | + } | |
| 25 | + return TWPrivateKeyIsValid(dataData, TWCurve(rawValue: curve.rawValue)) | |
| 26 | + } | |
| 27 | + | |
| 28 | + /// Convert the given private key to raw-bytes block of data | |
| 29 | + /// | |
| 30 | + /// - Parameter pk: Non-null pointer to the private key | |
| 31 | + /// - Returns: Non-null block of data (raw bytes) of the given private key | |
| 32 | + public var data: Data { | |
| 33 | + return TWDataNSData(TWPrivateKeyData(rawValue)) | |
| 34 | + } | |
| 35 | + | |
| 36 | + let rawValue: OpaquePointer | |
| 37 | + | |
| 38 | + init(rawValue: OpaquePointer) { | |
| 39 | + self.rawValue = rawValue | |
| 40 | + } | |
| 41 | + | |
| 42 | + public init() { | |
| 43 | + rawValue = TWPrivateKeyCreate() | |
| 44 | + } | |
| 45 | + | |
| 46 | + public init?(data: Data) { | |
| 47 | + let dataData = TWDataCreateWithNSData(data) | |
| 48 | + defer { | |
| 49 | + TWDataDelete(dataData) | |
| 50 | + } | |
| 51 | + guard let rawValue = TWPrivateKeyCreateWithData(dataData) else { | |
| 52 | + return nil | |
| 53 | + } | |
| 54 | + self.rawValue = rawValue | |
| 55 | + } | |
| 56 | + | |
| 57 | + public init?(key: PrivateKey) { | |
| 58 | + guard let rawValue = TWPrivateKeyCreateCopy(key.rawValue) else { | |
| 59 | + return nil | |
| 60 | + } | |
| 61 | + self.rawValue = rawValue | |
| 62 | + } | |
| 63 | + | |
| 64 | + deinit { | |
| 65 | + TWPrivateKeyDelete(rawValue) | |
| 66 | + } | |
| 67 | + | |
| 68 | + /// Returns the public key associated with the given coinType and privateKey | |
| 69 | + /// | |
| 70 | + /// - Parameter pk: Non-null pointer to the private key | |
| 71 | + /// - Parameter coinType: coinType of the given private key | |
| 72 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 73 | + public func getPublicKey(coinType: CoinType) -> PublicKey { | |
| 74 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKey(rawValue, TWCoinType(rawValue: coinType.rawValue))) | |
| 75 | + } | |
| 76 | + | |
| 77 | + /// Returns the public key associated with the given pubkeyType and privateKey | |
| 78 | + /// | |
| 79 | + /// - Parameter pk: Non-null pointer to the private key | |
| 80 | + /// - Parameter pubkeyType: pubkeyType of the given private key | |
| 81 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 82 | + public func getPublicKeyByType(pubkeyType: PublicKeyType) -> PublicKey { | |
| 83 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKeyByType(rawValue, TWPublicKeyType(rawValue: pubkeyType.rawValue))) | |
| 84 | + } | |
| 85 | + | |
| 86 | + /// Returns the Secp256k1 public key associated with the given private key | |
| 87 | + /// | |
| 88 | + /// - Parameter pk: Non-null pointer to the private key | |
| 89 | + /// - Parameter compressed: if the given private key is compressed or not | |
| 90 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 91 | + public func getPublicKeySecp256k1(compressed: Bool) -> PublicKey { | |
| 92 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKeySecp256k1(rawValue, compressed)) | |
| 93 | + } | |
| 94 | + | |
| 95 | + /// Returns the Nist256p1 public key associated with the given private key | |
| 96 | + /// | |
| 97 | + /// - Parameter pk: Non-null pointer to the private key | |
| 98 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 99 | + public func getPublicKeyNist256p1() -> PublicKey { | |
| 100 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKeyNist256p1(rawValue)) | |
| 101 | + } | |
| 102 | + | |
| 103 | + /// Returns the Ed25519 public key associated with the given private key | |
| 104 | + /// | |
| 105 | + /// - Parameter pk: Non-null pointer to the private key | |
| 106 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 107 | + public func getPublicKeyEd25519() -> PublicKey { | |
| 108 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKeyEd25519(rawValue)) | |
| 109 | + } | |
| 110 | + | |
| 111 | + /// Returns the Ed25519Blake2b public key associated with the given private key | |
| 112 | + /// | |
| 113 | + /// - Parameter pk: Non-null pointer to the private key | |
| 114 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 115 | + public func getPublicKeyEd25519Blake2b() -> PublicKey { | |
| 116 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKeyEd25519Blake2b(rawValue)) | |
| 117 | + } | |
| 118 | + | |
| 119 | + /// Returns the Ed25519Cardano public key associated with the given private key | |
| 120 | + /// | |
| 121 | + /// - Parameter pk: Non-null pointer to the private key | |
| 122 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 123 | + public func getPublicKeyEd25519Cardano() -> PublicKey { | |
| 124 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKeyEd25519Cardano(rawValue)) | |
| 125 | + } | |
| 126 | + | |
| 127 | + /// Returns the Curve25519 public key associated with the given private key | |
| 128 | + /// | |
| 129 | + /// - Parameter pk: Non-null pointer to the private key | |
| 130 | + /// - Returns: Non-null pointer to the corresponding public key | |
| 131 | + public func getPublicKeyCurve25519() -> PublicKey { | |
| 132 | + return PublicKey(rawValue: TWPrivateKeyGetPublicKeyCurve25519(rawValue)) | |
| 133 | + } | |
| 134 | + | |
| 135 | + /// Signs a digest using ECDSA and given curve. | |
| 136 | + /// | |
| 137 | + /// - Parameter pk: Non-null pointer to a Private key | |
| 138 | + /// - Parameter digest: Non-null digest block of data | |
| 139 | + /// - Parameter curve: Eliptic curve | |
| 140 | + /// - Returns: Signature as a Non-null block of data | |
| 141 | + public func sign(digest: Data, curve: Curve) -> Data? { | |
| 142 | + let digestData = TWDataCreateWithNSData(digest) | |
| 143 | + defer { | |
| 144 | + TWDataDelete(digestData) | |
| 145 | + } | |
| 146 | + guard let result = TWPrivateKeySign(rawValue, digestData, TWCurve(rawValue: curve.rawValue)) else { | |
| 147 | + return nil | |
| 148 | + } | |
| 149 | + return TWDataNSData(result) | |
| 150 | + } | |
| 151 | + | |
| 152 | + /// Signs a digest using ECDSA. The result is encoded with DER. | |
| 153 | + /// | |
| 154 | + /// - Parameter pk: Non-null pointer to a Private key | |
| 155 | + /// - Parameter digest: Non-null digest block of data | |
| 156 | + /// - Returns: Signature as a Non-null block of data | |
| 157 | + public func signAsDER(digest: Data) -> Data? { | |
| 158 | + let digestData = TWDataCreateWithNSData(digest) | |
| 159 | + defer { | |
| 160 | + TWDataDelete(digestData) | |
| 161 | + } | |
| 162 | + guard let result = TWPrivateKeySignAsDER(rawValue, digestData) else { | |
| 163 | + return nil | |
| 164 | + } | |
| 165 | + return TWDataNSData(result) | |
| 166 | + } | |
| 167 | + | |
| 168 | + /// Signs a digest using ECDSA and Zilliqa schnorr signature scheme. | |
| 169 | + /// | |
| 170 | + /// - Parameter pk: Non-null pointer to a Private key | |
| 171 | + /// - Parameter message: Non-null message | |
| 172 | + /// - Returns: Signature as a Non-null block of data | |
| 173 | + public func signZilliqaSchnorr(message: Data) -> Data? { | |
| 174 | + let messageData = TWDataCreateWithNSData(message) | |
| 175 | + defer { | |
| 176 | + TWDataDelete(messageData) | |
| 177 | + } | |
| 178 | + guard let result = TWPrivateKeySignZilliqaSchnorr(rawValue, messageData) else { | |
| 179 | + return nil | |
| 180 | + } | |
| 181 | + return TWDataNSData(result) | |
| 182 | + } | |
| 183 | + | |
| 184 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Aeternity+Proto.swift
+8 −0
@@ -0,0 +1,8 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public typealias AeternitySigningInput = TW_Aeternity_Proto_SigningInput | |
| 8 | +public typealias AeternitySigningOutput = TW_Aeternity_Proto_SigningOutput | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Aeternity.pb.swift
+209 −0
@@ -0,0 +1,209 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// DO NOT EDIT. | |
| 4 | +// swift-format-ignore-file | |
| 5 | +// | |
| 6 | +// Generated by the Swift generator plugin for the protocol buffer compiler. | |
| 7 | +// Source: Aeternity.proto | |
| 8 | +// | |
| 9 | +// For information on using the generated types, please see the documentation: | |
| 10 | +// https://github.com/apple/swift-protobuf/ | |
| 11 | + | |
| 12 | +import Foundation | |
| 13 | +import SwiftProtobuf | |
| 14 | + | |
| 15 | +// If the compiler emits an error on this type, it is because this file | |
| 16 | +// was generated by a version of the `protoc` Swift plug-in that is | |
| 17 | +// incompatible with the version of SwiftProtobuf.to which you are linking. | |
| 18 | +// Please ensure that you are building against the same version of the API | |
| 19 | +// that was used to generate this file. | |
| 20 | +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { | |
| 21 | + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} | |
| 22 | + typealias Version = _2 | |
| 23 | +} | |
| 24 | + | |
| 25 | +/// Input data necessary to create a signed transaction. | |
| 26 | +public struct TW_Aeternity_Proto_SigningInput { | |
| 27 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 28 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 29 | + // methods supported on all messages. | |
| 30 | + | |
| 31 | + /// Address of the sender with "ak_" prefix | |
| 32 | + public var fromAddress: String = String() | |
| 33 | + | |
| 34 | + /// Address of the recipient with "ak_" prefix | |
| 35 | + public var toAddress: String = String() | |
| 36 | + | |
| 37 | + /// Amount (uint256, serialized big endian) | |
| 38 | + public var amount: Data = Data() | |
| 39 | + | |
| 40 | + /// Fee amount (uint256, serialized big endian) | |
| 41 | + public var fee: Data = Data() | |
| 42 | + | |
| 43 | + /// Message, optional | |
| 44 | + public var payload: String = String() | |
| 45 | + | |
| 46 | + /// Time to live until block height | |
| 47 | + public var ttl: UInt64 = 0 | |
| 48 | + | |
| 49 | + /// Nonce (should be larger than in the last transaction of the account) | |
| 50 | + public var nonce: UInt64 = 0 | |
| 51 | + | |
| 52 | + /// The secret private key used for signing (32 bytes). | |
| 53 | + public var privateKey: Data = Data() | |
| 54 | + | |
| 55 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 56 | + | |
| 57 | + public init() {} | |
| 58 | +} | |
| 59 | + | |
| 60 | +/// Result containing the signed and encoded transaction. | |
| 61 | +public struct TW_Aeternity_Proto_SigningOutput { | |
| 62 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 63 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 64 | + // methods supported on all messages. | |
| 65 | + | |
| 66 | + /// Signed and encoded transaction bytes, Base64 with checksum | |
| 67 | + public var encoded: String = String() | |
| 68 | + | |
| 69 | + /// Signature, Base58 with checksum | |
| 70 | + public var signature: String = String() | |
| 71 | + | |
| 72 | + /// error code, 0 is ok, other codes will be treated as errors | |
| 73 | + public var error: TW_Common_Proto_SigningError = .ok | |
| 74 | + | |
| 75 | + /// error description | |
| 76 | + public var errorMessage: String = String() | |
| 77 | + | |
| 78 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 79 | + | |
| 80 | + public init() {} | |
| 81 | +} | |
| 82 | + | |
| 83 | +// MARK: - Code below here is support for the SwiftProtobuf.runtime. | |
| 84 | + | |
| 85 | +fileprivate let _protobuf_package = "TW.Aeternity.Proto" | |
| 86 | + | |
| 87 | +extension TW_Aeternity_Proto_SigningInput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 88 | + public static let protoMessageName: String = _protobuf_package + ".SigningInput" | |
| 89 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 90 | + 1: .standard(proto: "from_address"), | |
| 91 | + 2: .standard(proto: "to_address"), | |
| 92 | + 3: .same(proto: "amount"), | |
| 93 | + 4: .same(proto: "fee"), | |
| 94 | + 5: .same(proto: "payload"), | |
| 95 | + 6: .same(proto: "ttl"), | |
| 96 | + 7: .same(proto: "nonce"), | |
| 97 | + 8: .standard(proto: "private_key"), | |
| 98 | + ] | |
| 99 | + | |
| 100 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 101 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 102 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 103 | + // allocates stack space for every case branch when no optimizations are | |
| 104 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 105 | + switch fieldNumber { | |
| 106 | + case 1: try { try decoder.decodeSingularStringField(value: &self.fromAddress) }() | |
| 107 | + case 2: try { try decoder.decodeSingularStringField(value: &self.toAddress) }() | |
| 108 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.amount) }() | |
| 109 | + case 4: try { try decoder.decodeSingularBytesField(value: &self.fee) }() | |
| 110 | + case 5: try { try decoder.decodeSingularStringField(value: &self.payload) }() | |
| 111 | + case 6: try { try decoder.decodeSingularUInt64Field(value: &self.ttl) }() | |
| 112 | + case 7: try { try decoder.decodeSingularUInt64Field(value: &self.nonce) }() | |
| 113 | + case 8: try { try decoder.decodeSingularBytesField(value: &self.privateKey) }() | |
| 114 | + default: break | |
| 115 | + } | |
| 116 | + } | |
| 117 | + } | |
| 118 | + | |
| 119 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 120 | + if !self.fromAddress.isEmpty { | |
| 121 | + try visitor.visitSingularStringField(value: self.fromAddress, fieldNumber: 1) | |
| 122 | + } | |
| 123 | + if !self.toAddress.isEmpty { | |
| 124 | + try visitor.visitSingularStringField(value: self.toAddress, fieldNumber: 2) | |
| 125 | + } | |
| 126 | + if !self.amount.isEmpty { | |
| 127 | + try visitor.visitSingularBytesField(value: self.amount, fieldNumber: 3) | |
| 128 | + } | |
| 129 | + if !self.fee.isEmpty { | |
| 130 | + try visitor.visitSingularBytesField(value: self.fee, fieldNumber: 4) | |
| 131 | + } | |
| 132 | + if !self.payload.isEmpty { | |
| 133 | + try visitor.visitSingularStringField(value: self.payload, fieldNumber: 5) | |
| 134 | + } | |
| 135 | + if self.ttl != 0 { | |
| 136 | + try visitor.visitSingularUInt64Field(value: self.ttl, fieldNumber: 6) | |
| 137 | + } | |
| 138 | + if self.nonce != 0 { | |
| 139 | + try visitor.visitSingularUInt64Field(value: self.nonce, fieldNumber: 7) | |
| 140 | + } | |
| 141 | + if !self.privateKey.isEmpty { | |
| 142 | + try visitor.visitSingularBytesField(value: self.privateKey, fieldNumber: 8) | |
| 143 | + } | |
| 144 | + try unknownFields.traverse(visitor: &visitor) | |
| 145 | + } | |
| 146 | + | |
| 147 | + public static func ==(lhs: TW_Aeternity_Proto_SigningInput, rhs: TW_Aeternity_Proto_SigningInput) -> Bool { | |
| 148 | + if lhs.fromAddress != rhs.fromAddress {return false} | |
| 149 | + if lhs.toAddress != rhs.toAddress {return false} | |
| 150 | + if lhs.amount != rhs.amount {return false} | |
| 151 | + if lhs.fee != rhs.fee {return false} | |
| 152 | + if lhs.payload != rhs.payload {return false} | |
| 153 | + if lhs.ttl != rhs.ttl {return false} | |
| 154 | + if lhs.nonce != rhs.nonce {return false} | |
| 155 | + if lhs.privateKey != rhs.privateKey {return false} | |
| 156 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 157 | + return true | |
| 158 | + } | |
| 159 | +} | |
| 160 | + | |
| 161 | +extension TW_Aeternity_Proto_SigningOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 162 | + public static let protoMessageName: String = _protobuf_package + ".SigningOutput" | |
| 163 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 164 | + 1: .same(proto: "encoded"), | |
| 165 | + 2: .same(proto: "signature"), | |
| 166 | + 3: .same(proto: "error"), | |
| 167 | + 4: .standard(proto: "error_message"), | |
| 168 | + ] | |
| 169 | + | |
| 170 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 171 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 172 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 173 | + // allocates stack space for every case branch when no optimizations are | |
| 174 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 175 | + switch fieldNumber { | |
| 176 | + case 1: try { try decoder.decodeSingularStringField(value: &self.encoded) }() | |
| 177 | + case 2: try { try decoder.decodeSingularStringField(value: &self.signature) }() | |
| 178 | + case 3: try { try decoder.decodeSingularEnumField(value: &self.error) }() | |
| 179 | + case 4: try { try decoder.decodeSingularStringField(value: &self.errorMessage) }() | |
| 180 | + default: break | |
| 181 | + } | |
| 182 | + } | |
| 183 | + } | |
| 184 | + | |
| 185 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 186 | + if !self.encoded.isEmpty { | |
| 187 | + try visitor.visitSingularStringField(value: self.encoded, fieldNumber: 1) | |
| 188 | + } | |
| 189 | + if !self.signature.isEmpty { | |
| 190 | + try visitor.visitSingularStringField(value: self.signature, fieldNumber: 2) | |
| 191 | + } | |
| 192 | + if self.error != .ok { | |
| 193 | + try visitor.visitSingularEnumField(value: self.error, fieldNumber: 3) | |
| 194 | + } | |
| 195 | + if !self.errorMessage.isEmpty { | |
| 196 | + try visitor.visitSingularStringField(value: self.errorMessage, fieldNumber: 4) | |
| 197 | + } | |
| 198 | + try unknownFields.traverse(visitor: &visitor) | |
| 199 | + } | |
| 200 | + | |
| 201 | + public static func ==(lhs: TW_Aeternity_Proto_SigningOutput, rhs: TW_Aeternity_Proto_SigningOutput) -> Bool { | |
| 202 | + if lhs.encoded != rhs.encoded {return false} | |
| 203 | + if lhs.signature != rhs.signature {return false} | |
| 204 | + if lhs.error != rhs.error {return false} | |
| 205 | + if lhs.errorMessage != rhs.errorMessage {return false} | |
| 206 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 207 | + return true | |
| 208 | + } | |
| 209 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Aion+Proto.swift
+8 −0
@@ -0,0 +1,8 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public typealias AionSigningInput = TW_Aion_Proto_SigningInput | |
| 8 | +public typealias AionSigningOutput = TW_Aion_Proto_SigningOutput | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Aion.pb.swift
+209 −0
@@ -0,0 +1,209 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// DO NOT EDIT. | |
| 4 | +// swift-format-ignore-file | |
| 5 | +// | |
| 6 | +// Generated by the Swift generator plugin for the protocol buffer compiler. | |
| 7 | +// Source: Aion.proto | |
| 8 | +// | |
| 9 | +// For information on using the generated types, please see the documentation: | |
| 10 | +// https://github.com/apple/swift-protobuf/ | |
| 11 | + | |
| 12 | +import Foundation | |
| 13 | +import SwiftProtobuf | |
| 14 | + | |
| 15 | +// If the compiler emits an error on this type, it is because this file | |
| 16 | +// was generated by a version of the `protoc` Swift plug-in that is | |
| 17 | +// incompatible with the version of SwiftProtobuf.to which you are linking. | |
| 18 | +// Please ensure that you are building against the same version of the API | |
| 19 | +// that was used to generate this file. | |
| 20 | +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { | |
| 21 | + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} | |
| 22 | + typealias Version = _2 | |
| 23 | +} | |
| 24 | + | |
| 25 | +/// Input data necessary to create a signed transaction. | |
| 26 | +public struct TW_Aion_Proto_SigningInput { | |
| 27 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 28 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 29 | + // methods supported on all messages. | |
| 30 | + | |
| 31 | + /// Nonce (uint256, serialized big endian) | |
| 32 | + public var nonce: Data = Data() | |
| 33 | + | |
| 34 | + /// Gas price (uint256, serialized big endian) | |
| 35 | + public var gasPrice: Data = Data() | |
| 36 | + | |
| 37 | + /// Gas limit (uint256, serialized big endian) | |
| 38 | + public var gasLimit: Data = Data() | |
| 39 | + | |
| 40 | + /// Recipient's address. | |
| 41 | + public var toAddress: String = String() | |
| 42 | + | |
| 43 | + /// Amount to send in wei (uint256, serialized big endian) | |
| 44 | + public var amount: Data = Data() | |
| 45 | + | |
| 46 | + /// Optional payload | |
| 47 | + public var payload: Data = Data() | |
| 48 | + | |
| 49 | + /// The secret private key used for signing (32 bytes). | |
| 50 | + public var privateKey: Data = Data() | |
| 51 | + | |
| 52 | + /// Timestamp | |
| 53 | + public var timestamp: UInt64 = 0 | |
| 54 | + | |
| 55 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 56 | + | |
| 57 | + public init() {} | |
| 58 | +} | |
| 59 | + | |
| 60 | +/// Result containing the signed and encoded transaction. | |
| 61 | +public struct TW_Aion_Proto_SigningOutput { | |
| 62 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 63 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 64 | + // methods supported on all messages. | |
| 65 | + | |
| 66 | + /// Signed and encoded transaction bytes. | |
| 67 | + public var encoded: Data = Data() | |
| 68 | + | |
| 69 | + /// Signature. | |
| 70 | + public var signature: Data = Data() | |
| 71 | + | |
| 72 | + /// error code, 0 is ok, other codes will be treated as errors | |
| 73 | + public var error: TW_Common_Proto_SigningError = .ok | |
| 74 | + | |
| 75 | + /// error description | |
| 76 | + public var errorMessage: String = String() | |
| 77 | + | |
| 78 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 79 | + | |
| 80 | + public init() {} | |
| 81 | +} | |
| 82 | + | |
| 83 | +// MARK: - Code below here is support for the SwiftProtobuf.runtime. | |
| 84 | + | |
| 85 | +fileprivate let _protobuf_package = "TW.Aion.Proto" | |
| 86 | + | |
| 87 | +extension TW_Aion_Proto_SigningInput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 88 | + public static let protoMessageName: String = _protobuf_package + ".SigningInput" | |
| 89 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 90 | + 1: .same(proto: "nonce"), | |
| 91 | + 2: .standard(proto: "gas_price"), | |
| 92 | + 3: .standard(proto: "gas_limit"), | |
| 93 | + 4: .standard(proto: "to_address"), | |
| 94 | + 5: .same(proto: "amount"), | |
| 95 | + 6: .same(proto: "payload"), | |
| 96 | + 7: .standard(proto: "private_key"), | |
| 97 | + 8: .same(proto: "timestamp"), | |
| 98 | + ] | |
| 99 | + | |
| 100 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 101 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 102 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 103 | + // allocates stack space for every case branch when no optimizations are | |
| 104 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 105 | + switch fieldNumber { | |
| 106 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.nonce) }() | |
| 107 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.gasPrice) }() | |
| 108 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.gasLimit) }() | |
| 109 | + case 4: try { try decoder.decodeSingularStringField(value: &self.toAddress) }() | |
| 110 | + case 5: try { try decoder.decodeSingularBytesField(value: &self.amount) }() | |
| 111 | + case 6: try { try decoder.decodeSingularBytesField(value: &self.payload) }() | |
| 112 | + case 7: try { try decoder.decodeSingularBytesField(value: &self.privateKey) }() | |
| 113 | + case 8: try { try decoder.decodeSingularUInt64Field(value: &self.timestamp) }() | |
| 114 | + default: break | |
| 115 | + } | |
| 116 | + } | |
| 117 | + } | |
| 118 | + | |
| 119 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 120 | + if !self.nonce.isEmpty { | |
| 121 | + try visitor.visitSingularBytesField(value: self.nonce, fieldNumber: 1) | |
| 122 | + } | |
| 123 | + if !self.gasPrice.isEmpty { | |
| 124 | + try visitor.visitSingularBytesField(value: self.gasPrice, fieldNumber: 2) | |
| 125 | + } | |
| 126 | + if !self.gasLimit.isEmpty { | |
| 127 | + try visitor.visitSingularBytesField(value: self.gasLimit, fieldNumber: 3) | |
| 128 | + } | |
| 129 | + if !self.toAddress.isEmpty { | |
| 130 | + try visitor.visitSingularStringField(value: self.toAddress, fieldNumber: 4) | |
| 131 | + } | |
| 132 | + if !self.amount.isEmpty { | |
| 133 | + try visitor.visitSingularBytesField(value: self.amount, fieldNumber: 5) | |
| 134 | + } | |
| 135 | + if !self.payload.isEmpty { | |
| 136 | + try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 6) | |
| 137 | + } | |
| 138 | + if !self.privateKey.isEmpty { | |
| 139 | + try visitor.visitSingularBytesField(value: self.privateKey, fieldNumber: 7) | |
| 140 | + } | |
| 141 | + if self.timestamp != 0 { | |
| 142 | + try visitor.visitSingularUInt64Field(value: self.timestamp, fieldNumber: 8) | |
| 143 | + } | |
| 144 | + try unknownFields.traverse(visitor: &visitor) | |
| 145 | + } | |
| 146 | + | |
| 147 | + public static func ==(lhs: TW_Aion_Proto_SigningInput, rhs: TW_Aion_Proto_SigningInput) -> Bool { | |
| 148 | + if lhs.nonce != rhs.nonce {return false} | |
| 149 | + if lhs.gasPrice != rhs.gasPrice {return false} | |
| 150 | + if lhs.gasLimit != rhs.gasLimit {return false} | |
| 151 | + if lhs.toAddress != rhs.toAddress {return false} | |
| 152 | + if lhs.amount != rhs.amount {return false} | |
| 153 | + if lhs.payload != rhs.payload {return false} | |
| 154 | + if lhs.privateKey != rhs.privateKey {return false} | |
| 155 | + if lhs.timestamp != rhs.timestamp {return false} | |
| 156 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 157 | + return true | |
| 158 | + } | |
| 159 | +} | |
| 160 | + | |
| 161 | +extension TW_Aion_Proto_SigningOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 162 | + public static let protoMessageName: String = _protobuf_package + ".SigningOutput" | |
| 163 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 164 | + 1: .same(proto: "encoded"), | |
| 165 | + 2: .same(proto: "signature"), | |
| 166 | + 3: .same(proto: "error"), | |
| 167 | + 4: .standard(proto: "error_message"), | |
| 168 | + ] | |
| 169 | + | |
| 170 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 171 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 172 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 173 | + // allocates stack space for every case branch when no optimizations are | |
| 174 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 175 | + switch fieldNumber { | |
| 176 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.encoded) }() | |
| 177 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.signature) }() | |
| 178 | + case 3: try { try decoder.decodeSingularEnumField(value: &self.error) }() | |
| 179 | + case 4: try { try decoder.decodeSingularStringField(value: &self.errorMessage) }() | |
| 180 | + default: break | |
| 181 | + } | |
| 182 | + } | |
| 183 | + } | |
| 184 | + | |
| 185 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 186 | + if !self.encoded.isEmpty { | |
| 187 | + try visitor.visitSingularBytesField(value: self.encoded, fieldNumber: 1) | |
| 188 | + } | |
| 189 | + if !self.signature.isEmpty { | |
| 190 | + try visitor.visitSingularBytesField(value: self.signature, fieldNumber: 2) | |
| 191 | + } | |
| 192 | + if self.error != .ok { | |
| 193 | + try visitor.visitSingularEnumField(value: self.error, fieldNumber: 3) | |
| 194 | + } | |
| 195 | + if !self.errorMessage.isEmpty { | |
| 196 | + try visitor.visitSingularStringField(value: self.errorMessage, fieldNumber: 4) | |
| 197 | + } | |
| 198 | + try unknownFields.traverse(visitor: &visitor) | |
| 199 | + } | |
| 200 | + | |
| 201 | + public static func ==(lhs: TW_Aion_Proto_SigningOutput, rhs: TW_Aion_Proto_SigningOutput) -> Bool { | |
| 202 | + if lhs.encoded != rhs.encoded {return false} | |
| 203 | + if lhs.signature != rhs.signature {return false} | |
| 204 | + if lhs.error != rhs.error {return false} | |
| 205 | + if lhs.errorMessage != rhs.errorMessage {return false} | |
| 206 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 207 | + return true | |
| 208 | + } | |
| 209 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Algorand+Proto.swift
+11 −0
@@ -0,0 +1,11 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public typealias AlgorandTransfer = TW_Algorand_Proto_Transfer | |
| 8 | +public typealias AlgorandAssetTransfer = TW_Algorand_Proto_AssetTransfer | |
| 9 | +public typealias AlgorandAssetOptIn = TW_Algorand_Proto_AssetOptIn | |
| 10 | +public typealias AlgorandSigningInput = TW_Algorand_Proto_SigningInput | |
| 11 | +public typealias AlgorandSigningOutput = TW_Algorand_Proto_SigningOutput | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Algorand.pb.swift
+493 −0
@@ -0,0 +1,493 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// DO NOT EDIT. | |
| 4 | +// swift-format-ignore-file | |
| 5 | +// | |
| 6 | +// Generated by the Swift generator plugin for the protocol buffer compiler. | |
| 7 | +// Source: Algorand.proto | |
| 8 | +// | |
| 9 | +// For information on using the generated types, please see the documentation: | |
| 10 | +// https://github.com/apple/swift-protobuf/ | |
| 11 | + | |
| 12 | +import Foundation | |
| 13 | +import SwiftProtobuf | |
| 14 | + | |
| 15 | +// If the compiler emits an error on this type, it is because this file | |
| 16 | +// was generated by a version of the `protoc` Swift plug-in that is | |
| 17 | +// incompatible with the version of SwiftProtobuf.to which you are linking. | |
| 18 | +// Please ensure that you are building against the same version of the API | |
| 19 | +// that was used to generate this file. | |
| 20 | +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { | |
| 21 | + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} | |
| 22 | + typealias Version = _2 | |
| 23 | +} | |
| 24 | + | |
| 25 | +/// Simple transfer message, transfer an amount to an address | |
| 26 | +public struct TW_Algorand_Proto_Transfer { | |
| 27 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 28 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 29 | + // methods supported on all messages. | |
| 30 | + | |
| 31 | + /// Destination address (string) | |
| 32 | + public var toAddress: String = String() | |
| 33 | + | |
| 34 | + /// Amount | |
| 35 | + public var amount: UInt64 = 0 | |
| 36 | + | |
| 37 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 38 | + | |
| 39 | + public init() {} | |
| 40 | +} | |
| 41 | + | |
| 42 | +/// Asset Transfer message, with assetID | |
| 43 | +public struct TW_Algorand_Proto_AssetTransfer { | |
| 44 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 45 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 46 | + // methods supported on all messages. | |
| 47 | + | |
| 48 | + /// Destination address (string) | |
| 49 | + public var toAddress: String = String() | |
| 50 | + | |
| 51 | + /// Amount | |
| 52 | + public var amount: UInt64 = 0 | |
| 53 | + | |
| 54 | + /// ID of the asset being transferred | |
| 55 | + public var assetID: UInt64 = 0 | |
| 56 | + | |
| 57 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 58 | + | |
| 59 | + public init() {} | |
| 60 | +} | |
| 61 | + | |
| 62 | +/// Opt-in message for an asset | |
| 63 | +public struct TW_Algorand_Proto_AssetOptIn { | |
| 64 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 65 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 66 | + // methods supported on all messages. | |
| 67 | + | |
| 68 | + /// ID of the asset | |
| 69 | + public var assetID: UInt64 = 0 | |
| 70 | + | |
| 71 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 72 | + | |
| 73 | + public init() {} | |
| 74 | +} | |
| 75 | + | |
| 76 | +/// Input data necessary to create a signed transaction. | |
| 77 | +public struct TW_Algorand_Proto_SigningInput { | |
| 78 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 79 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 80 | + // methods supported on all messages. | |
| 81 | + | |
| 82 | + /// network / chain id | |
| 83 | + public var genesisID: String = String() | |
| 84 | + | |
| 85 | + /// network / chain hash | |
| 86 | + public var genesisHash: Data = Data() | |
| 87 | + | |
| 88 | + /// binary note data | |
| 89 | + public var note: Data = Data() | |
| 90 | + | |
| 91 | + /// The secret private key used for signing (32 bytes). | |
| 92 | + public var privateKey: Data = Data() | |
| 93 | + | |
| 94 | + /// network / first round | |
| 95 | + public var firstRound: UInt64 = 0 | |
| 96 | + | |
| 97 | + /// network / last round | |
| 98 | + public var lastRound: UInt64 = 0 | |
| 99 | + | |
| 100 | + /// fee amount | |
| 101 | + public var fee: UInt64 = 0 | |
| 102 | + | |
| 103 | + /// public key | |
| 104 | + public var publicKey: Data = Data() | |
| 105 | + | |
| 106 | + /// message payload | |
| 107 | + public var messageOneof: TW_Algorand_Proto_SigningInput.OneOf_MessageOneof? = nil | |
| 108 | + | |
| 109 | + public var transfer: TW_Algorand_Proto_Transfer { | |
| 110 | + get { | |
| 111 | + if case .transfer(let v)? = messageOneof {return v} | |
| 112 | + return TW_Algorand_Proto_Transfer() | |
| 113 | + } | |
| 114 | + set {messageOneof = .transfer(newValue)} | |
| 115 | + } | |
| 116 | + | |
| 117 | + public var assetTransfer: TW_Algorand_Proto_AssetTransfer { | |
| 118 | + get { | |
| 119 | + if case .assetTransfer(let v)? = messageOneof {return v} | |
| 120 | + return TW_Algorand_Proto_AssetTransfer() | |
| 121 | + } | |
| 122 | + set {messageOneof = .assetTransfer(newValue)} | |
| 123 | + } | |
| 124 | + | |
| 125 | + public var assetOptIn: TW_Algorand_Proto_AssetOptIn { | |
| 126 | + get { | |
| 127 | + if case .assetOptIn(let v)? = messageOneof {return v} | |
| 128 | + return TW_Algorand_Proto_AssetOptIn() | |
| 129 | + } | |
| 130 | + set {messageOneof = .assetOptIn(newValue)} | |
| 131 | + } | |
| 132 | + | |
| 133 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 134 | + | |
| 135 | + /// message payload | |
| 136 | + public enum OneOf_MessageOneof: Equatable { | |
| 137 | + case transfer(TW_Algorand_Proto_Transfer) | |
| 138 | + case assetTransfer(TW_Algorand_Proto_AssetTransfer) | |
| 139 | + case assetOptIn(TW_Algorand_Proto_AssetOptIn) | |
| 140 | + | |
| 141 | + #if !swift(>=4.1) | |
| 142 | + public static func ==(lhs: TW_Algorand_Proto_SigningInput.OneOf_MessageOneof, rhs: TW_Algorand_Proto_SigningInput.OneOf_MessageOneof) -> Bool { | |
| 143 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 144 | + // allocates stack space for every case branch when no optimizations are | |
| 145 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 146 | + switch (lhs, rhs) { | |
| 147 | + case (.transfer, .transfer): return { | |
| 148 | + guard case .transfer(let l) = lhs, case .transfer(let r) = rhs else { preconditionFailure() } | |
| 149 | + return l == r | |
| 150 | + }() | |
| 151 | + case (.assetTransfer, .assetTransfer): return { | |
| 152 | + guard case .assetTransfer(let l) = lhs, case .assetTransfer(let r) = rhs else { preconditionFailure() } | |
| 153 | + return l == r | |
| 154 | + }() | |
| 155 | + case (.assetOptIn, .assetOptIn): return { | |
| 156 | + guard case .assetOptIn(let l) = lhs, case .assetOptIn(let r) = rhs else { preconditionFailure() } | |
| 157 | + return l == r | |
| 158 | + }() | |
| 159 | + default: return false | |
| 160 | + } | |
| 161 | + } | |
| 162 | + #endif | |
| 163 | + } | |
| 164 | + | |
| 165 | + public init() {} | |
| 166 | +} | |
| 167 | + | |
| 168 | +/// Result containing the signed and encoded transaction. | |
| 169 | +public struct TW_Algorand_Proto_SigningOutput { | |
| 170 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 171 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 172 | + // methods supported on all messages. | |
| 173 | + | |
| 174 | + /// Signed and encoded transaction bytes. | |
| 175 | + public var encoded: Data = Data() | |
| 176 | + | |
| 177 | + /// Signature in base64. | |
| 178 | + public var signature: String = String() | |
| 179 | + | |
| 180 | + /// Error code, 0 is ok, other codes will be treated as errors. | |
| 181 | + public var error: TW_Common_Proto_SigningError = .ok | |
| 182 | + | |
| 183 | + /// Error description. | |
| 184 | + public var errorMessage: String = String() | |
| 185 | + | |
| 186 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 187 | + | |
| 188 | + public init() {} | |
| 189 | +} | |
| 190 | + | |
| 191 | +// MARK: - Code below here is support for the SwiftProtobuf.runtime. | |
| 192 | + | |
| 193 | +fileprivate let _protobuf_package = "TW.Algorand.Proto" | |
| 194 | + | |
| 195 | +extension TW_Algorand_Proto_Transfer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 196 | + public static let protoMessageName: String = _protobuf_package + ".Transfer" | |
| 197 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 198 | + 1: .standard(proto: "to_address"), | |
| 199 | + 2: .same(proto: "amount"), | |
| 200 | + ] | |
| 201 | + | |
| 202 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 203 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 204 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 205 | + // allocates stack space for every case branch when no optimizations are | |
| 206 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 207 | + switch fieldNumber { | |
| 208 | + case 1: try { try decoder.decodeSingularStringField(value: &self.toAddress) }() | |
| 209 | + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 210 | + default: break | |
| 211 | + } | |
| 212 | + } | |
| 213 | + } | |
| 214 | + | |
| 215 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 216 | + if !self.toAddress.isEmpty { | |
| 217 | + try visitor.visitSingularStringField(value: self.toAddress, fieldNumber: 1) | |
| 218 | + } | |
| 219 | + if self.amount != 0 { | |
| 220 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 2) | |
| 221 | + } | |
| 222 | + try unknownFields.traverse(visitor: &visitor) | |
| 223 | + } | |
| 224 | + | |
| 225 | + public static func ==(lhs: TW_Algorand_Proto_Transfer, rhs: TW_Algorand_Proto_Transfer) -> Bool { | |
| 226 | + if lhs.toAddress != rhs.toAddress {return false} | |
| 227 | + if lhs.amount != rhs.amount {return false} | |
| 228 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 229 | + return true | |
| 230 | + } | |
| 231 | +} | |
| 232 | + | |
| 233 | +extension TW_Algorand_Proto_AssetTransfer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 234 | + public static let protoMessageName: String = _protobuf_package + ".AssetTransfer" | |
| 235 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 236 | + 1: .standard(proto: "to_address"), | |
| 237 | + 2: .same(proto: "amount"), | |
| 238 | + 3: .standard(proto: "asset_id"), | |
| 239 | + ] | |
| 240 | + | |
| 241 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 242 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 243 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 244 | + // allocates stack space for every case branch when no optimizations are | |
| 245 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 246 | + switch fieldNumber { | |
| 247 | + case 1: try { try decoder.decodeSingularStringField(value: &self.toAddress) }() | |
| 248 | + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 249 | + case 3: try { try decoder.decodeSingularUInt64Field(value: &self.assetID) }() | |
| 250 | + default: break | |
| 251 | + } | |
| 252 | + } | |
| 253 | + } | |
| 254 | + | |
| 255 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 256 | + if !self.toAddress.isEmpty { | |
| 257 | + try visitor.visitSingularStringField(value: self.toAddress, fieldNumber: 1) | |
| 258 | + } | |
| 259 | + if self.amount != 0 { | |
| 260 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 2) | |
| 261 | + } | |
| 262 | + if self.assetID != 0 { | |
| 263 | + try visitor.visitSingularUInt64Field(value: self.assetID, fieldNumber: 3) | |
| 264 | + } | |
| 265 | + try unknownFields.traverse(visitor: &visitor) | |
| 266 | + } | |
| 267 | + | |
| 268 | + public static func ==(lhs: TW_Algorand_Proto_AssetTransfer, rhs: TW_Algorand_Proto_AssetTransfer) -> Bool { | |
| 269 | + if lhs.toAddress != rhs.toAddress {return false} | |
| 270 | + if lhs.amount != rhs.amount {return false} | |
| 271 | + if lhs.assetID != rhs.assetID {return false} | |
| 272 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 273 | + return true | |
| 274 | + } | |
| 275 | +} | |
| 276 | + | |
| 277 | +extension TW_Algorand_Proto_AssetOptIn: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 278 | + public static let protoMessageName: String = _protobuf_package + ".AssetOptIn" | |
| 279 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 280 | + 1: .standard(proto: "asset_id"), | |
| 281 | + ] | |
| 282 | + | |
| 283 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 284 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 285 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 286 | + // allocates stack space for every case branch when no optimizations are | |
| 287 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 288 | + switch fieldNumber { | |
| 289 | + case 1: try { try decoder.decodeSingularUInt64Field(value: &self.assetID) }() | |
| 290 | + default: break | |
| 291 | + } | |
| 292 | + } | |
| 293 | + } | |
| 294 | + | |
| 295 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 296 | + if self.assetID != 0 { | |
| 297 | + try visitor.visitSingularUInt64Field(value: self.assetID, fieldNumber: 1) | |
| 298 | + } | |
| 299 | + try unknownFields.traverse(visitor: &visitor) | |
| 300 | + } | |
| 301 | + | |
| 302 | + public static func ==(lhs: TW_Algorand_Proto_AssetOptIn, rhs: TW_Algorand_Proto_AssetOptIn) -> Bool { | |
| 303 | + if lhs.assetID != rhs.assetID {return false} | |
| 304 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 305 | + return true | |
| 306 | + } | |
| 307 | +} | |
| 308 | + | |
| 309 | +extension TW_Algorand_Proto_SigningInput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 310 | + public static let protoMessageName: String = _protobuf_package + ".SigningInput" | |
| 311 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 312 | + 1: .standard(proto: "genesis_id"), | |
| 313 | + 2: .standard(proto: "genesis_hash"), | |
| 314 | + 3: .same(proto: "note"), | |
| 315 | + 4: .standard(proto: "private_key"), | |
| 316 | + 5: .standard(proto: "first_round"), | |
| 317 | + 6: .standard(proto: "last_round"), | |
| 318 | + 7: .same(proto: "fee"), | |
| 319 | + 8: .standard(proto: "public_key"), | |
| 320 | + 10: .same(proto: "transfer"), | |
| 321 | + 11: .standard(proto: "asset_transfer"), | |
| 322 | + 12: .standard(proto: "asset_opt_in"), | |
| 323 | + ] | |
| 324 | + | |
| 325 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 326 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 327 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 328 | + // allocates stack space for every case branch when no optimizations are | |
| 329 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 330 | + switch fieldNumber { | |
| 331 | + case 1: try { try decoder.decodeSingularStringField(value: &self.genesisID) }() | |
| 332 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.genesisHash) }() | |
| 333 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.note) }() | |
| 334 | + case 4: try { try decoder.decodeSingularBytesField(value: &self.privateKey) }() | |
| 335 | + case 5: try { try decoder.decodeSingularUInt64Field(value: &self.firstRound) }() | |
| 336 | + case 6: try { try decoder.decodeSingularUInt64Field(value: &self.lastRound) }() | |
| 337 | + case 7: try { try decoder.decodeSingularUInt64Field(value: &self.fee) }() | |
| 338 | + case 8: try { try decoder.decodeSingularBytesField(value: &self.publicKey) }() | |
| 339 | + case 10: try { | |
| 340 | + var v: TW_Algorand_Proto_Transfer? | |
| 341 | + var hadOneofValue = false | |
| 342 | + if let current = self.messageOneof { | |
| 343 | + hadOneofValue = true | |
| 344 | + if case .transfer(let m) = current {v = m} | |
| 345 | + } | |
| 346 | + try decoder.decodeSingularMessageField(value: &v) | |
| 347 | + if let v = v { | |
| 348 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 349 | + self.messageOneof = .transfer(v) | |
| 350 | + } | |
| 351 | + }() | |
| 352 | + case 11: try { | |
| 353 | + var v: TW_Algorand_Proto_AssetTransfer? | |
| 354 | + var hadOneofValue = false | |
| 355 | + if let current = self.messageOneof { | |
| 356 | + hadOneofValue = true | |
| 357 | + if case .assetTransfer(let m) = current {v = m} | |
| 358 | + } | |
| 359 | + try decoder.decodeSingularMessageField(value: &v) | |
| 360 | + if let v = v { | |
| 361 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 362 | + self.messageOneof = .assetTransfer(v) | |
| 363 | + } | |
| 364 | + }() | |
| 365 | + case 12: try { | |
| 366 | + var v: TW_Algorand_Proto_AssetOptIn? | |
| 367 | + var hadOneofValue = false | |
| 368 | + if let current = self.messageOneof { | |
| 369 | + hadOneofValue = true | |
| 370 | + if case .assetOptIn(let m) = current {v = m} | |
| 371 | + } | |
| 372 | + try decoder.decodeSingularMessageField(value: &v) | |
| 373 | + if let v = v { | |
| 374 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 375 | + self.messageOneof = .assetOptIn(v) | |
| 376 | + } | |
| 377 | + }() | |
| 378 | + default: break | |
| 379 | + } | |
| 380 | + } | |
| 381 | + } | |
| 382 | + | |
| 383 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 384 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 385 | + // allocates stack space for every if/case branch local when no optimizations | |
| 386 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 387 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 388 | + if !self.genesisID.isEmpty { | |
| 389 | + try visitor.visitSingularStringField(value: self.genesisID, fieldNumber: 1) | |
| 390 | + } | |
| 391 | + if !self.genesisHash.isEmpty { | |
| 392 | + try visitor.visitSingularBytesField(value: self.genesisHash, fieldNumber: 2) | |
| 393 | + } | |
| 394 | + if !self.note.isEmpty { | |
| 395 | + try visitor.visitSingularBytesField(value: self.note, fieldNumber: 3) | |
| 396 | + } | |
| 397 | + if !self.privateKey.isEmpty { | |
| 398 | + try visitor.visitSingularBytesField(value: self.privateKey, fieldNumber: 4) | |
| 399 | + } | |
| 400 | + if self.firstRound != 0 { | |
| 401 | + try visitor.visitSingularUInt64Field(value: self.firstRound, fieldNumber: 5) | |
| 402 | + } | |
| 403 | + if self.lastRound != 0 { | |
| 404 | + try visitor.visitSingularUInt64Field(value: self.lastRound, fieldNumber: 6) | |
| 405 | + } | |
| 406 | + if self.fee != 0 { | |
| 407 | + try visitor.visitSingularUInt64Field(value: self.fee, fieldNumber: 7) | |
| 408 | + } | |
| 409 | + if !self.publicKey.isEmpty { | |
| 410 | + try visitor.visitSingularBytesField(value: self.publicKey, fieldNumber: 8) | |
| 411 | + } | |
| 412 | + switch self.messageOneof { | |
| 413 | + case .transfer?: try { | |
| 414 | + guard case .transfer(let v)? = self.messageOneof else { preconditionFailure() } | |
| 415 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 10) | |
| 416 | + }() | |
| 417 | + case .assetTransfer?: try { | |
| 418 | + guard case .assetTransfer(let v)? = self.messageOneof else { preconditionFailure() } | |
| 419 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 11) | |
| 420 | + }() | |
| 421 | + case .assetOptIn?: try { | |
| 422 | + guard case .assetOptIn(let v)? = self.messageOneof else { preconditionFailure() } | |
| 423 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 12) | |
| 424 | + }() | |
| 425 | + case nil: break | |
| 426 | + } | |
| 427 | + try unknownFields.traverse(visitor: &visitor) | |
| 428 | + } | |
| 429 | + | |
| 430 | + public static func ==(lhs: TW_Algorand_Proto_SigningInput, rhs: TW_Algorand_Proto_SigningInput) -> Bool { | |
| 431 | + if lhs.genesisID != rhs.genesisID {return false} | |
| 432 | + if lhs.genesisHash != rhs.genesisHash {return false} | |
| 433 | + if lhs.note != rhs.note {return false} | |
| 434 | + if lhs.privateKey != rhs.privateKey {return false} | |
| 435 | + if lhs.firstRound != rhs.firstRound {return false} | |
| 436 | + if lhs.lastRound != rhs.lastRound {return false} | |
| 437 | + if lhs.fee != rhs.fee {return false} | |
| 438 | + if lhs.publicKey != rhs.publicKey {return false} | |
| 439 | + if lhs.messageOneof != rhs.messageOneof {return false} | |
| 440 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 441 | + return true | |
| 442 | + } | |
| 443 | +} | |
| 444 | + | |
| 445 | +extension TW_Algorand_Proto_SigningOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 446 | + public static let protoMessageName: String = _protobuf_package + ".SigningOutput" | |
| 447 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 448 | + 1: .same(proto: "encoded"), | |
| 449 | + 2: .same(proto: "signature"), | |
| 450 | + 3: .same(proto: "error"), | |
| 451 | + 4: .standard(proto: "error_message"), | |
| 452 | + ] | |
| 453 | + | |
| 454 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 455 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 456 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 457 | + // allocates stack space for every case branch when no optimizations are | |
| 458 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 459 | + switch fieldNumber { | |
| 460 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.encoded) }() | |
| 461 | + case 2: try { try decoder.decodeSingularStringField(value: &self.signature) }() | |
| 462 | + case 3: try { try decoder.decodeSingularEnumField(value: &self.error) }() | |
| 463 | + case 4: try { try decoder.decodeSingularStringField(value: &self.errorMessage) }() | |
| 464 | + default: break | |
| 465 | + } | |
| 466 | + } | |
| 467 | + } | |
| 468 | + | |
| 469 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 470 | + if !self.encoded.isEmpty { | |
| 471 | + try visitor.visitSingularBytesField(value: self.encoded, fieldNumber: 1) | |
| 472 | + } | |
| 473 | + if !self.signature.isEmpty { | |
| 474 | + try visitor.visitSingularStringField(value: self.signature, fieldNumber: 2) | |
| 475 | + } | |
| 476 | + if self.error != .ok { | |
| 477 | + try visitor.visitSingularEnumField(value: self.error, fieldNumber: 3) | |
| 478 | + } | |
| 479 | + if !self.errorMessage.isEmpty { | |
| 480 | + try visitor.visitSingularStringField(value: self.errorMessage, fieldNumber: 4) | |
| 481 | + } | |
| 482 | + try unknownFields.traverse(visitor: &visitor) | |
| 483 | + } | |
| 484 | + | |
| 485 | + public static func ==(lhs: TW_Algorand_Proto_SigningOutput, rhs: TW_Algorand_Proto_SigningOutput) -> Bool { | |
| 486 | + if lhs.encoded != rhs.encoded {return false} | |
| 487 | + if lhs.signature != rhs.signature {return false} | |
| 488 | + if lhs.error != rhs.error {return false} | |
| 489 | + if lhs.errorMessage != rhs.errorMessage {return false} | |
| 490 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 491 | + return true | |
| 492 | + } | |
| 493 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Aptos+Proto.swift
+23 −0
@@ -0,0 +1,23 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public typealias AptosTransferMessage = TW_Aptos_Proto_TransferMessage | |
| 8 | +public typealias AptosStructTag = TW_Aptos_Proto_StructTag | |
| 9 | +public typealias AptosTokenTransferMessage = TW_Aptos_Proto_TokenTransferMessage | |
| 10 | +public typealias AptosTokenTransferCoinsMessage = TW_Aptos_Proto_TokenTransferCoinsMessage | |
| 11 | +public typealias AptosFungibleAssetTransferMessage = TW_Aptos_Proto_FungibleAssetTransferMessage | |
| 12 | +public typealias AptosCreateAccountMessage = TW_Aptos_Proto_CreateAccountMessage | |
| 13 | +public typealias AptosOfferNftMessage = TW_Aptos_Proto_OfferNftMessage | |
| 14 | +public typealias AptosCancelOfferNftMessage = TW_Aptos_Proto_CancelOfferNftMessage | |
| 15 | +public typealias AptosClaimNftMessage = TW_Aptos_Proto_ClaimNftMessage | |
| 16 | +public typealias AptosTortugaClaim = TW_Aptos_Proto_TortugaClaim | |
| 17 | +public typealias AptosTortugaStake = TW_Aptos_Proto_TortugaStake | |
| 18 | +public typealias AptosTortugaUnstake = TW_Aptos_Proto_TortugaUnstake | |
| 19 | +public typealias AptosLiquidStaking = TW_Aptos_Proto_LiquidStaking | |
| 20 | +public typealias AptosNftMessage = TW_Aptos_Proto_NftMessage | |
| 21 | +public typealias AptosSigningInput = TW_Aptos_Proto_SigningInput | |
| 22 | +public typealias AptosTransactionAuthenticator = TW_Aptos_Proto_TransactionAuthenticator | |
| 23 | +public typealias AptosSigningOutput = TW_Aptos_Proto_SigningOutput | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Aptos.pb.swift
+1636 −0
@@ -0,0 +1,1636 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// DO NOT EDIT. | |
| 4 | +// swift-format-ignore-file | |
| 5 | +// | |
| 6 | +// Generated by the Swift generator plugin for the protocol buffer compiler. | |
| 7 | +// Source: Aptos.proto | |
| 8 | +// | |
| 9 | +// For information on using the generated types, please see the documentation: | |
| 10 | +// https://github.com/apple/swift-protobuf/ | |
| 11 | + | |
| 12 | +// SPDX-License-Identifier: Apache-2.0 | |
| 13 | +// | |
| 14 | +// Copyright © 2017 Trust Wallet. | |
| 15 | + | |
| 16 | +import Foundation | |
| 17 | +import SwiftProtobuf | |
| 18 | + | |
| 19 | +// If the compiler emits an error on this type, it is because this file | |
| 20 | +// was generated by a version of the `protoc` Swift plug-in that is | |
| 21 | +// incompatible with the version of SwiftProtobuf.to which you are linking. | |
| 22 | +// Please ensure that you are building against the same version of the API | |
| 23 | +// that was used to generate this file. | |
| 24 | +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { | |
| 25 | + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} | |
| 26 | + typealias Version = _2 | |
| 27 | +} | |
| 28 | + | |
| 29 | +/// Necessary fields to process a TransferMessage | |
| 30 | +public struct TW_Aptos_Proto_TransferMessage { | |
| 31 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 32 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 33 | + // methods supported on all messages. | |
| 34 | + | |
| 35 | + /// Destination Account address (string) | |
| 36 | + public var to: String = String() | |
| 37 | + | |
| 38 | + /// Amount to be transferred (uint64) | |
| 39 | + public var amount: UInt64 = 0 | |
| 40 | + | |
| 41 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 42 | + | |
| 43 | + public init() {} | |
| 44 | +} | |
| 45 | + | |
| 46 | +/// Necessary tag for type function argument | |
| 47 | +public struct TW_Aptos_Proto_StructTag { | |
| 48 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 49 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 50 | + // methods supported on all messages. | |
| 51 | + | |
| 52 | + /// Address of the account | |
| 53 | + public var accountAddress: String = String() | |
| 54 | + | |
| 55 | + /// Module name | |
| 56 | + public var module: String = String() | |
| 57 | + | |
| 58 | + /// Identifier | |
| 59 | + public var name: String = String() | |
| 60 | + | |
| 61 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 62 | + | |
| 63 | + public init() {} | |
| 64 | +} | |
| 65 | + | |
| 66 | +/// Necessary fields to process a `0x1::coin::transfer` function. | |
| 67 | +public struct TW_Aptos_Proto_TokenTransferMessage { | |
| 68 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 69 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 70 | + // methods supported on all messages. | |
| 71 | + | |
| 72 | + /// Destination Account address (string) | |
| 73 | + public var to: String = String() | |
| 74 | + | |
| 75 | + /// Amount to be transferred (uint64) | |
| 76 | + public var amount: UInt64 = 0 | |
| 77 | + | |
| 78 | + /// token function to call, e.g BTC: 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC | |
| 79 | + public var function: TW_Aptos_Proto_StructTag { | |
| 80 | + get {return _function ?? TW_Aptos_Proto_StructTag()} | |
| 81 | + set {_function = newValue} | |
| 82 | + } | |
| 83 | + /// Returns true if `function` has been explicitly set. | |
| 84 | + public var hasFunction: Bool {return self._function != nil} | |
| 85 | + /// Clears the value of `function`. Subsequent reads from it will return its default value. | |
| 86 | + public mutating func clearFunction() {self._function = nil} | |
| 87 | + | |
| 88 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 89 | + | |
| 90 | + public init() {} | |
| 91 | + | |
| 92 | + fileprivate var _function: TW_Aptos_Proto_StructTag? = nil | |
| 93 | +} | |
| 94 | + | |
| 95 | +/// Necessary fields to process a `0x1::aptos_account::transfer_coins` function. | |
| 96 | +/// Can be used to transfer tokens with registering the recipient account if needed. | |
| 97 | +public struct TW_Aptos_Proto_TokenTransferCoinsMessage { | |
| 98 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 99 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 100 | + // methods supported on all messages. | |
| 101 | + | |
| 102 | + /// Destination Account address (string) | |
| 103 | + public var to: String = String() | |
| 104 | + | |
| 105 | + /// Amount to be transferred (uint64) | |
| 106 | + public var amount: UInt64 = 0 | |
| 107 | + | |
| 108 | + /// token function to call, e.g BTC: 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC | |
| 109 | + public var function: TW_Aptos_Proto_StructTag { | |
| 110 | + get {return _function ?? TW_Aptos_Proto_StructTag()} | |
| 111 | + set {_function = newValue} | |
| 112 | + } | |
| 113 | + /// Returns true if `function` has been explicitly set. | |
| 114 | + public var hasFunction: Bool {return self._function != nil} | |
| 115 | + /// Clears the value of `function`. Subsequent reads from it will return its default value. | |
| 116 | + public mutating func clearFunction() {self._function = nil} | |
| 117 | + | |
| 118 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 119 | + | |
| 120 | + public init() {} | |
| 121 | + | |
| 122 | + fileprivate var _function: TW_Aptos_Proto_StructTag? = nil | |
| 123 | +} | |
| 124 | + | |
| 125 | +public struct TW_Aptos_Proto_FungibleAssetTransferMessage { | |
| 126 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 127 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 128 | + // methods supported on all messages. | |
| 129 | + | |
| 130 | + /// Fungible Asset address (string) | |
| 131 | + public var metadataAddress: String = String() | |
| 132 | + | |
| 133 | + /// Destination Account address (string) | |
| 134 | + public var to: String = String() | |
| 135 | + | |
| 136 | + /// Amount to be transferred (uint64) | |
| 137 | + public var amount: UInt64 = 0 | |
| 138 | + | |
| 139 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 140 | + | |
| 141 | + public init() {} | |
| 142 | +} | |
| 143 | + | |
| 144 | +/// Necessary fields to process a CreateAccountMessage | |
| 145 | +public struct TW_Aptos_Proto_CreateAccountMessage { | |
| 146 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 147 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 148 | + // methods supported on all messages. | |
| 149 | + | |
| 150 | + /// auth account address to create | |
| 151 | + public var authKey: String = String() | |
| 152 | + | |
| 153 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 154 | + | |
| 155 | + public init() {} | |
| 156 | +} | |
| 157 | + | |
| 158 | +/// Necessary fields to process an OfferNftMessage | |
| 159 | +public struct TW_Aptos_Proto_OfferNftMessage { | |
| 160 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 161 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 162 | + // methods supported on all messages. | |
| 163 | + | |
| 164 | + /// Receiver address | |
| 165 | + public var receiver: String = String() | |
| 166 | + | |
| 167 | + /// Creator address | |
| 168 | + public var creator: String = String() | |
| 169 | + | |
| 170 | + /// Name of the collection | |
| 171 | + public var collectionName: String = String() | |
| 172 | + | |
| 173 | + /// Name of the NFT | |
| 174 | + public var name: String = String() | |
| 175 | + | |
| 176 | + /// Property version (should be often 0) | |
| 177 | + public var propertyVersion: UInt64 = 0 | |
| 178 | + | |
| 179 | + /// Amount of NFT's to transfer (should be often 1) | |
| 180 | + public var amount: UInt64 = 0 | |
| 181 | + | |
| 182 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 183 | + | |
| 184 | + public init() {} | |
| 185 | +} | |
| 186 | + | |
| 187 | +/// Necessary fields to process an CancelOfferNftMessage | |
| 188 | +public struct TW_Aptos_Proto_CancelOfferNftMessage { | |
| 189 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 190 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 191 | + // methods supported on all messages. | |
| 192 | + | |
| 193 | + /// Receiver address | |
| 194 | + public var receiver: String = String() | |
| 195 | + | |
| 196 | + /// Creator address | |
| 197 | + public var creator: String = String() | |
| 198 | + | |
| 199 | + /// Name of the collection | |
| 200 | + public var collectionName: String = String() | |
| 201 | + | |
| 202 | + /// Name of the NFT | |
| 203 | + public var name: String = String() | |
| 204 | + | |
| 205 | + /// Property version (should be often 0) | |
| 206 | + public var propertyVersion: UInt64 = 0 | |
| 207 | + | |
| 208 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 209 | + | |
| 210 | + public init() {} | |
| 211 | +} | |
| 212 | + | |
| 213 | +/// Necessary fields to process an ClaimNftMessage | |
| 214 | +public struct TW_Aptos_Proto_ClaimNftMessage { | |
| 215 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 216 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 217 | + // methods supported on all messages. | |
| 218 | + | |
| 219 | + /// Sender address | |
| 220 | + public var sender: String = String() | |
| 221 | + | |
| 222 | + /// Creator address | |
| 223 | + public var creator: String = String() | |
| 224 | + | |
| 225 | + /// Name of the collection | |
| 226 | + public var collectionName: String = String() | |
| 227 | + | |
| 228 | + /// Name of the NFT | |
| 229 | + public var name: String = String() | |
| 230 | + | |
| 231 | + /// Property version (should be often 0) | |
| 232 | + public var propertyVersion: UInt64 = 0 | |
| 233 | + | |
| 234 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 235 | + | |
| 236 | + public init() {} | |
| 237 | +} | |
| 238 | + | |
| 239 | +public struct TW_Aptos_Proto_TortugaClaim { | |
| 240 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 241 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 242 | + // methods supported on all messages. | |
| 243 | + | |
| 244 | + /// idx of ticket to claim | |
| 245 | + public var idx: UInt64 = 0 | |
| 246 | + | |
| 247 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 248 | + | |
| 249 | + public init() {} | |
| 250 | +} | |
| 251 | + | |
| 252 | +public struct TW_Aptos_Proto_TortugaStake { | |
| 253 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 254 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 255 | + // methods supported on all messages. | |
| 256 | + | |
| 257 | + /// Amount to be stake | |
| 258 | + public var amount: UInt64 = 0 | |
| 259 | + | |
| 260 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 261 | + | |
| 262 | + public init() {} | |
| 263 | +} | |
| 264 | + | |
| 265 | +public struct TW_Aptos_Proto_TortugaUnstake { | |
| 266 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 267 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 268 | + // methods supported on all messages. | |
| 269 | + | |
| 270 | + /// Amount to be stake | |
| 271 | + public var amount: UInt64 = 0 | |
| 272 | + | |
| 273 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 274 | + | |
| 275 | + public init() {} | |
| 276 | +} | |
| 277 | + | |
| 278 | +public struct TW_Aptos_Proto_LiquidStaking { | |
| 279 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 280 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 281 | + // methods supported on all messages. | |
| 282 | + | |
| 283 | + /// Smart contract address of liquid staking module | |
| 284 | + public var smartContractAddress: String = String() | |
| 285 | + | |
| 286 | + public var liquidStakeTransactionPayload: TW_Aptos_Proto_LiquidStaking.OneOf_LiquidStakeTransactionPayload? = nil | |
| 287 | + | |
| 288 | + public var stake: TW_Aptos_Proto_TortugaStake { | |
| 289 | + get { | |
| 290 | + if case .stake(let v)? = liquidStakeTransactionPayload {return v} | |
| 291 | + return TW_Aptos_Proto_TortugaStake() | |
| 292 | + } | |
| 293 | + set {liquidStakeTransactionPayload = .stake(newValue)} | |
| 294 | + } | |
| 295 | + | |
| 296 | + public var unstake: TW_Aptos_Proto_TortugaUnstake { | |
| 297 | + get { | |
| 298 | + if case .unstake(let v)? = liquidStakeTransactionPayload {return v} | |
| 299 | + return TW_Aptos_Proto_TortugaUnstake() | |
| 300 | + } | |
| 301 | + set {liquidStakeTransactionPayload = .unstake(newValue)} | |
| 302 | + } | |
| 303 | + | |
| 304 | + public var claim: TW_Aptos_Proto_TortugaClaim { | |
| 305 | + get { | |
| 306 | + if case .claim(let v)? = liquidStakeTransactionPayload {return v} | |
| 307 | + return TW_Aptos_Proto_TortugaClaim() | |
| 308 | + } | |
| 309 | + set {liquidStakeTransactionPayload = .claim(newValue)} | |
| 310 | + } | |
| 311 | + | |
| 312 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 313 | + | |
| 314 | + public enum OneOf_LiquidStakeTransactionPayload: Equatable { | |
| 315 | + case stake(TW_Aptos_Proto_TortugaStake) | |
| 316 | + case unstake(TW_Aptos_Proto_TortugaUnstake) | |
| 317 | + case claim(TW_Aptos_Proto_TortugaClaim) | |
| 318 | + | |
| 319 | + #if !swift(>=4.1) | |
| 320 | + public static func ==(lhs: TW_Aptos_Proto_LiquidStaking.OneOf_LiquidStakeTransactionPayload, rhs: TW_Aptos_Proto_LiquidStaking.OneOf_LiquidStakeTransactionPayload) -> Bool { | |
| 321 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 322 | + // allocates stack space for every case branch when no optimizations are | |
| 323 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 324 | + switch (lhs, rhs) { | |
| 325 | + case (.stake, .stake): return { | |
| 326 | + guard case .stake(let l) = lhs, case .stake(let r) = rhs else { preconditionFailure() } | |
| 327 | + return l == r | |
| 328 | + }() | |
| 329 | + case (.unstake, .unstake): return { | |
| 330 | + guard case .unstake(let l) = lhs, case .unstake(let r) = rhs else { preconditionFailure() } | |
| 331 | + return l == r | |
| 332 | + }() | |
| 333 | + case (.claim, .claim): return { | |
| 334 | + guard case .claim(let l) = lhs, case .claim(let r) = rhs else { preconditionFailure() } | |
| 335 | + return l == r | |
| 336 | + }() | |
| 337 | + default: return false | |
| 338 | + } | |
| 339 | + } | |
| 340 | + #endif | |
| 341 | + } | |
| 342 | + | |
| 343 | + public init() {} | |
| 344 | +} | |
| 345 | + | |
| 346 | +public struct TW_Aptos_Proto_NftMessage { | |
| 347 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 348 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 349 | + // methods supported on all messages. | |
| 350 | + | |
| 351 | + public var nftTransactionPayload: TW_Aptos_Proto_NftMessage.OneOf_NftTransactionPayload? = nil | |
| 352 | + | |
| 353 | + public var offerNft: TW_Aptos_Proto_OfferNftMessage { | |
| 354 | + get { | |
| 355 | + if case .offerNft(let v)? = nftTransactionPayload {return v} | |
| 356 | + return TW_Aptos_Proto_OfferNftMessage() | |
| 357 | + } | |
| 358 | + set {nftTransactionPayload = .offerNft(newValue)} | |
| 359 | + } | |
| 360 | + | |
| 361 | + public var cancelOfferNft: TW_Aptos_Proto_CancelOfferNftMessage { | |
| 362 | + get { | |
| 363 | + if case .cancelOfferNft(let v)? = nftTransactionPayload {return v} | |
| 364 | + return TW_Aptos_Proto_CancelOfferNftMessage() | |
| 365 | + } | |
| 366 | + set {nftTransactionPayload = .cancelOfferNft(newValue)} | |
| 367 | + } | |
| 368 | + | |
| 369 | + public var claimNft: TW_Aptos_Proto_ClaimNftMessage { | |
| 370 | + get { | |
| 371 | + if case .claimNft(let v)? = nftTransactionPayload {return v} | |
| 372 | + return TW_Aptos_Proto_ClaimNftMessage() | |
| 373 | + } | |
| 374 | + set {nftTransactionPayload = .claimNft(newValue)} | |
| 375 | + } | |
| 376 | + | |
| 377 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 378 | + | |
| 379 | + public enum OneOf_NftTransactionPayload: Equatable { | |
| 380 | + case offerNft(TW_Aptos_Proto_OfferNftMessage) | |
| 381 | + case cancelOfferNft(TW_Aptos_Proto_CancelOfferNftMessage) | |
| 382 | + case claimNft(TW_Aptos_Proto_ClaimNftMessage) | |
| 383 | + | |
| 384 | + #if !swift(>=4.1) | |
| 385 | + public static func ==(lhs: TW_Aptos_Proto_NftMessage.OneOf_NftTransactionPayload, rhs: TW_Aptos_Proto_NftMessage.OneOf_NftTransactionPayload) -> Bool { | |
| 386 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 387 | + // allocates stack space for every case branch when no optimizations are | |
| 388 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 389 | + switch (lhs, rhs) { | |
| 390 | + case (.offerNft, .offerNft): return { | |
| 391 | + guard case .offerNft(let l) = lhs, case .offerNft(let r) = rhs else { preconditionFailure() } | |
| 392 | + return l == r | |
| 393 | + }() | |
| 394 | + case (.cancelOfferNft, .cancelOfferNft): return { | |
| 395 | + guard case .cancelOfferNft(let l) = lhs, case .cancelOfferNft(let r) = rhs else { preconditionFailure() } | |
| 396 | + return l == r | |
| 397 | + }() | |
| 398 | + case (.claimNft, .claimNft): return { | |
| 399 | + guard case .claimNft(let l) = lhs, case .claimNft(let r) = rhs else { preconditionFailure() } | |
| 400 | + return l == r | |
| 401 | + }() | |
| 402 | + default: return false | |
| 403 | + } | |
| 404 | + } | |
| 405 | + #endif | |
| 406 | + } | |
| 407 | + | |
| 408 | + public init() {} | |
| 409 | +} | |
| 410 | + | |
| 411 | +/// Input data necessary to create a signed transaction. | |
| 412 | +public struct TW_Aptos_Proto_SigningInput { | |
| 413 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 414 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 415 | + // methods supported on all messages. | |
| 416 | + | |
| 417 | + /// Sender Account address (string) | |
| 418 | + public var sender: String = String() | |
| 419 | + | |
| 420 | + /// Sequence number, incremented atomically for each tx present on the account, start at 0 (int64) | |
| 421 | + public var sequenceNumber: Int64 = 0 | |
| 422 | + | |
| 423 | + /// Max gas amount that the user is willing to pay (uint64) | |
| 424 | + public var maxGasAmount: UInt64 = 0 | |
| 425 | + | |
| 426 | + /// Gas unit price - queried through API (uint64) | |
| 427 | + public var gasUnitPrice: UInt64 = 0 | |
| 428 | + | |
| 429 | + /// Expiration timestamp for the transaction, can't be in the past (uint64) | |
| 430 | + public var expirationTimestampSecs: UInt64 = 0 | |
| 431 | + | |
| 432 | + /// Chain id 1 (mainnet) 32(devnet) (uint32 - casted in uint8_t later) | |
| 433 | + public var chainID: UInt32 = 0 | |
| 434 | + | |
| 435 | + /// Private key to sign the transaction (bytes) | |
| 436 | + public var privateKey: Data = Data() | |
| 437 | + | |
| 438 | + /// hex encoded function to sign, use it for smart contract approval (string) | |
| 439 | + public var anyEncoded: String = String() | |
| 440 | + | |
| 441 | + public var transactionPayload: TW_Aptos_Proto_SigningInput.OneOf_TransactionPayload? = nil | |
| 442 | + | |
| 443 | + public var transfer: TW_Aptos_Proto_TransferMessage { | |
| 444 | + get { | |
| 445 | + if case .transfer(let v)? = transactionPayload {return v} | |
| 446 | + return TW_Aptos_Proto_TransferMessage() | |
| 447 | + } | |
| 448 | + set {transactionPayload = .transfer(newValue)} | |
| 449 | + } | |
| 450 | + | |
| 451 | + public var tokenTransfer: TW_Aptos_Proto_TokenTransferMessage { | |
| 452 | + get { | |
| 453 | + if case .tokenTransfer(let v)? = transactionPayload {return v} | |
| 454 | + return TW_Aptos_Proto_TokenTransferMessage() | |
| 455 | + } | |
| 456 | + set {transactionPayload = .tokenTransfer(newValue)} | |
| 457 | + } | |
| 458 | + | |
| 459 | + public var createAccount: TW_Aptos_Proto_CreateAccountMessage { | |
| 460 | + get { | |
| 461 | + if case .createAccount(let v)? = transactionPayload {return v} | |
| 462 | + return TW_Aptos_Proto_CreateAccountMessage() | |
| 463 | + } | |
| 464 | + set {transactionPayload = .createAccount(newValue)} | |
| 465 | + } | |
| 466 | + | |
| 467 | + public var nftMessage: TW_Aptos_Proto_NftMessage { | |
| 468 | + get { | |
| 469 | + if case .nftMessage(let v)? = transactionPayload {return v} | |
| 470 | + return TW_Aptos_Proto_NftMessage() | |
| 471 | + } | |
| 472 | + set {transactionPayload = .nftMessage(newValue)} | |
| 473 | + } | |
| 474 | + | |
| 475 | + public var liquidStakingMessage: TW_Aptos_Proto_LiquidStaking { | |
| 476 | + get { | |
| 477 | + if case .liquidStakingMessage(let v)? = transactionPayload {return v} | |
| 478 | + return TW_Aptos_Proto_LiquidStaking() | |
| 479 | + } | |
| 480 | + set {transactionPayload = .liquidStakingMessage(newValue)} | |
| 481 | + } | |
| 482 | + | |
| 483 | + public var tokenTransferCoins: TW_Aptos_Proto_TokenTransferCoinsMessage { | |
| 484 | + get { | |
| 485 | + if case .tokenTransferCoins(let v)? = transactionPayload {return v} | |
| 486 | + return TW_Aptos_Proto_TokenTransferCoinsMessage() | |
| 487 | + } | |
| 488 | + set {transactionPayload = .tokenTransferCoins(newValue)} | |
| 489 | + } | |
| 490 | + | |
| 491 | + public var fungibleAssetTransfer: TW_Aptos_Proto_FungibleAssetTransferMessage { | |
| 492 | + get { | |
| 493 | + if case .fungibleAssetTransfer(let v)? = transactionPayload {return v} | |
| 494 | + return TW_Aptos_Proto_FungibleAssetTransferMessage() | |
| 495 | + } | |
| 496 | + set {transactionPayload = .fungibleAssetTransfer(newValue)} | |
| 497 | + } | |
| 498 | + | |
| 499 | + public var abi: String = String() | |
| 500 | + | |
| 501 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 502 | + | |
| 503 | + public enum OneOf_TransactionPayload: Equatable { | |
| 504 | + case transfer(TW_Aptos_Proto_TransferMessage) | |
| 505 | + case tokenTransfer(TW_Aptos_Proto_TokenTransferMessage) | |
| 506 | + case createAccount(TW_Aptos_Proto_CreateAccountMessage) | |
| 507 | + case nftMessage(TW_Aptos_Proto_NftMessage) | |
| 508 | + case liquidStakingMessage(TW_Aptos_Proto_LiquidStaking) | |
| 509 | + case tokenTransferCoins(TW_Aptos_Proto_TokenTransferCoinsMessage) | |
| 510 | + case fungibleAssetTransfer(TW_Aptos_Proto_FungibleAssetTransferMessage) | |
| 511 | + | |
| 512 | + #if !swift(>=4.1) | |
| 513 | + public static func ==(lhs: TW_Aptos_Proto_SigningInput.OneOf_TransactionPayload, rhs: TW_Aptos_Proto_SigningInput.OneOf_TransactionPayload) -> Bool { | |
| 514 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 515 | + // allocates stack space for every case branch when no optimizations are | |
| 516 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 517 | + switch (lhs, rhs) { | |
| 518 | + case (.transfer, .transfer): return { | |
| 519 | + guard case .transfer(let l) = lhs, case .transfer(let r) = rhs else { preconditionFailure() } | |
| 520 | + return l == r | |
| 521 | + }() | |
| 522 | + case (.tokenTransfer, .tokenTransfer): return { | |
| 523 | + guard case .tokenTransfer(let l) = lhs, case .tokenTransfer(let r) = rhs else { preconditionFailure() } | |
| 524 | + return l == r | |
| 525 | + }() | |
| 526 | + case (.createAccount, .createAccount): return { | |
| 527 | + guard case .createAccount(let l) = lhs, case .createAccount(let r) = rhs else { preconditionFailure() } | |
| 528 | + return l == r | |
| 529 | + }() | |
| 530 | + case (.nftMessage, .nftMessage): return { | |
| 531 | + guard case .nftMessage(let l) = lhs, case .nftMessage(let r) = rhs else { preconditionFailure() } | |
| 532 | + return l == r | |
| 533 | + }() | |
| 534 | + case (.liquidStakingMessage, .liquidStakingMessage): return { | |
| 535 | + guard case .liquidStakingMessage(let l) = lhs, case .liquidStakingMessage(let r) = rhs else { preconditionFailure() } | |
| 536 | + return l == r | |
| 537 | + }() | |
| 538 | + case (.tokenTransferCoins, .tokenTransferCoins): return { | |
| 539 | + guard case .tokenTransferCoins(let l) = lhs, case .tokenTransferCoins(let r) = rhs else { preconditionFailure() } | |
| 540 | + return l == r | |
| 541 | + }() | |
| 542 | + case (.fungibleAssetTransfer, .fungibleAssetTransfer): return { | |
| 543 | + guard case .fungibleAssetTransfer(let l) = lhs, case .fungibleAssetTransfer(let r) = rhs else { preconditionFailure() } | |
| 544 | + return l == r | |
| 545 | + }() | |
| 546 | + default: return false | |
| 547 | + } | |
| 548 | + } | |
| 549 | + #endif | |
| 550 | + } | |
| 551 | + | |
| 552 | + public init() {} | |
| 553 | +} | |
| 554 | + | |
| 555 | +/// Information related to the signed transaction | |
| 556 | +public struct TW_Aptos_Proto_TransactionAuthenticator { | |
| 557 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 558 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 559 | + // methods supported on all messages. | |
| 560 | + | |
| 561 | + /// Signature part of the signed transaction (bytes) | |
| 562 | + public var signature: Data = Data() | |
| 563 | + | |
| 564 | + /// Public key of the signer (bytes) | |
| 565 | + public var publicKey: Data = Data() | |
| 566 | + | |
| 567 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 568 | + | |
| 569 | + public init() {} | |
| 570 | +} | |
| 571 | + | |
| 572 | +/// Transaction signing output. | |
| 573 | +public struct TW_Aptos_Proto_SigningOutput { | |
| 574 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 575 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 576 | + // methods supported on all messages. | |
| 577 | + | |
| 578 | + //// The raw transaction (bytes) | |
| 579 | + public var rawTxn: Data = Data() | |
| 580 | + | |
| 581 | + //// Public key and signature to authenticate | |
| 582 | + public var authenticator: TW_Aptos_Proto_TransactionAuthenticator { | |
| 583 | + get {return _authenticator ?? TW_Aptos_Proto_TransactionAuthenticator()} | |
| 584 | + set {_authenticator = newValue} | |
| 585 | + } | |
| 586 | + /// Returns true if `authenticator` has been explicitly set. | |
| 587 | + public var hasAuthenticator: Bool {return self._authenticator != nil} | |
| 588 | + /// Clears the value of `authenticator`. Subsequent reads from it will return its default value. | |
| 589 | + public mutating func clearAuthenticator() {self._authenticator = nil} | |
| 590 | + | |
| 591 | + //// Signed and encoded transaction bytes. | |
| 592 | + public var encoded: Data = Data() | |
| 593 | + | |
| 594 | + /// Transaction json format for api broadcasting (string) | |
| 595 | + public var json: String = String() | |
| 596 | + | |
| 597 | + /// Error code, 0 is ok, other codes will be treated as errors. | |
| 598 | + public var error: TW_Common_Proto_SigningError = .ok | |
| 599 | + | |
| 600 | + /// Error description. | |
| 601 | + public var errorMessage: String = String() | |
| 602 | + | |
| 603 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 604 | + | |
| 605 | + public init() {} | |
| 606 | + | |
| 607 | + fileprivate var _authenticator: TW_Aptos_Proto_TransactionAuthenticator? = nil | |
| 608 | +} | |
| 609 | + | |
| 610 | +// MARK: - Code below here is support for the SwiftProtobuf.runtime. | |
| 611 | + | |
| 612 | +fileprivate let _protobuf_package = "TW.Aptos.Proto" | |
| 613 | + | |
| 614 | +extension TW_Aptos_Proto_TransferMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 615 | + public static let protoMessageName: String = _protobuf_package + ".TransferMessage" | |
| 616 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 617 | + 1: .same(proto: "to"), | |
| 618 | + 2: .same(proto: "amount"), | |
| 619 | + ] | |
| 620 | + | |
| 621 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 622 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 623 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 624 | + // allocates stack space for every case branch when no optimizations are | |
| 625 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 626 | + switch fieldNumber { | |
| 627 | + case 1: try { try decoder.decodeSingularStringField(value: &self.to) }() | |
| 628 | + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 629 | + default: break | |
| 630 | + } | |
| 631 | + } | |
| 632 | + } | |
| 633 | + | |
| 634 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 635 | + if !self.to.isEmpty { | |
| 636 | + try visitor.visitSingularStringField(value: self.to, fieldNumber: 1) | |
| 637 | + } | |
| 638 | + if self.amount != 0 { | |
| 639 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 2) | |
| 640 | + } | |
| 641 | + try unknownFields.traverse(visitor: &visitor) | |
| 642 | + } | |
| 643 | + | |
| 644 | + public static func ==(lhs: TW_Aptos_Proto_TransferMessage, rhs: TW_Aptos_Proto_TransferMessage) -> Bool { | |
| 645 | + if lhs.to != rhs.to {return false} | |
| 646 | + if lhs.amount != rhs.amount {return false} | |
| 647 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 648 | + return true | |
| 649 | + } | |
| 650 | +} | |
| 651 | + | |
| 652 | +extension TW_Aptos_Proto_StructTag: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 653 | + public static let protoMessageName: String = _protobuf_package + ".StructTag" | |
| 654 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 655 | + 1: .standard(proto: "account_address"), | |
| 656 | + 2: .same(proto: "module"), | |
| 657 | + 3: .same(proto: "name"), | |
| 658 | + ] | |
| 659 | + | |
| 660 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 661 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 662 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 663 | + // allocates stack space for every case branch when no optimizations are | |
| 664 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 665 | + switch fieldNumber { | |
| 666 | + case 1: try { try decoder.decodeSingularStringField(value: &self.accountAddress) }() | |
| 667 | + case 2: try { try decoder.decodeSingularStringField(value: &self.module) }() | |
| 668 | + case 3: try { try decoder.decodeSingularStringField(value: &self.name) }() | |
| 669 | + default: break | |
| 670 | + } | |
| 671 | + } | |
| 672 | + } | |
| 673 | + | |
| 674 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 675 | + if !self.accountAddress.isEmpty { | |
| 676 | + try visitor.visitSingularStringField(value: self.accountAddress, fieldNumber: 1) | |
| 677 | + } | |
| 678 | + if !self.module.isEmpty { | |
| 679 | + try visitor.visitSingularStringField(value: self.module, fieldNumber: 2) | |
| 680 | + } | |
| 681 | + if !self.name.isEmpty { | |
| 682 | + try visitor.visitSingularStringField(value: self.name, fieldNumber: 3) | |
| 683 | + } | |
| 684 | + try unknownFields.traverse(visitor: &visitor) | |
| 685 | + } | |
| 686 | + | |
| 687 | + public static func ==(lhs: TW_Aptos_Proto_StructTag, rhs: TW_Aptos_Proto_StructTag) -> Bool { | |
| 688 | + if lhs.accountAddress != rhs.accountAddress {return false} | |
| 689 | + if lhs.module != rhs.module {return false} | |
| 690 | + if lhs.name != rhs.name {return false} | |
| 691 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 692 | + return true | |
| 693 | + } | |
| 694 | +} | |
| 695 | + | |
| 696 | +extension TW_Aptos_Proto_TokenTransferMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 697 | + public static let protoMessageName: String = _protobuf_package + ".TokenTransferMessage" | |
| 698 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 699 | + 1: .same(proto: "to"), | |
| 700 | + 2: .same(proto: "amount"), | |
| 701 | + 3: .same(proto: "function"), | |
| 702 | + ] | |
| 703 | + | |
| 704 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 705 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 706 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 707 | + // allocates stack space for every case branch when no optimizations are | |
| 708 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 709 | + switch fieldNumber { | |
| 710 | + case 1: try { try decoder.decodeSingularStringField(value: &self.to) }() | |
| 711 | + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 712 | + case 3: try { try decoder.decodeSingularMessageField(value: &self._function) }() | |
| 713 | + default: break | |
| 714 | + } | |
| 715 | + } | |
| 716 | + } | |
| 717 | + | |
| 718 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 719 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 720 | + // allocates stack space for every if/case branch local when no optimizations | |
| 721 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 722 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 723 | + if !self.to.isEmpty { | |
| 724 | + try visitor.visitSingularStringField(value: self.to, fieldNumber: 1) | |
| 725 | + } | |
| 726 | + if self.amount != 0 { | |
| 727 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 2) | |
| 728 | + } | |
| 729 | + try { if let v = self._function { | |
| 730 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) | |
| 731 | + } }() | |
| 732 | + try unknownFields.traverse(visitor: &visitor) | |
| 733 | + } | |
| 734 | + | |
| 735 | + public static func ==(lhs: TW_Aptos_Proto_TokenTransferMessage, rhs: TW_Aptos_Proto_TokenTransferMessage) -> Bool { | |
| 736 | + if lhs.to != rhs.to {return false} | |
| 737 | + if lhs.amount != rhs.amount {return false} | |
| 738 | + if lhs._function != rhs._function {return false} | |
| 739 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 740 | + return true | |
| 741 | + } | |
| 742 | +} | |
| 743 | + | |
| 744 | +extension TW_Aptos_Proto_TokenTransferCoinsMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 745 | + public static let protoMessageName: String = _protobuf_package + ".TokenTransferCoinsMessage" | |
| 746 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 747 | + 1: .same(proto: "to"), | |
| 748 | + 2: .same(proto: "amount"), | |
| 749 | + 3: .same(proto: "function"), | |
| 750 | + ] | |
| 751 | + | |
| 752 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 753 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 754 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 755 | + // allocates stack space for every case branch when no optimizations are | |
| 756 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 757 | + switch fieldNumber { | |
| 758 | + case 1: try { try decoder.decodeSingularStringField(value: &self.to) }() | |
| 759 | + case 2: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 760 | + case 3: try { try decoder.decodeSingularMessageField(value: &self._function) }() | |
| 761 | + default: break | |
| 762 | + } | |
| 763 | + } | |
| 764 | + } | |
| 765 | + | |
| 766 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 767 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 768 | + // allocates stack space for every if/case branch local when no optimizations | |
| 769 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 770 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 771 | + if !self.to.isEmpty { | |
| 772 | + try visitor.visitSingularStringField(value: self.to, fieldNumber: 1) | |
| 773 | + } | |
| 774 | + if self.amount != 0 { | |
| 775 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 2) | |
| 776 | + } | |
| 777 | + try { if let v = self._function { | |
| 778 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) | |
| 779 | + } }() | |
| 780 | + try unknownFields.traverse(visitor: &visitor) | |
| 781 | + } | |
| 782 | + | |
| 783 | + public static func ==(lhs: TW_Aptos_Proto_TokenTransferCoinsMessage, rhs: TW_Aptos_Proto_TokenTransferCoinsMessage) -> Bool { | |
| 784 | + if lhs.to != rhs.to {return false} | |
| 785 | + if lhs.amount != rhs.amount {return false} | |
| 786 | + if lhs._function != rhs._function {return false} | |
| 787 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 788 | + return true | |
| 789 | + } | |
| 790 | +} | |
| 791 | + | |
| 792 | +extension TW_Aptos_Proto_FungibleAssetTransferMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 793 | + public static let protoMessageName: String = _protobuf_package + ".FungibleAssetTransferMessage" | |
| 794 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 795 | + 1: .standard(proto: "metadata_address"), | |
| 796 | + 2: .same(proto: "to"), | |
| 797 | + 3: .same(proto: "amount"), | |
| 798 | + ] | |
| 799 | + | |
| 800 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 801 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 802 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 803 | + // allocates stack space for every case branch when no optimizations are | |
| 804 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 805 | + switch fieldNumber { | |
| 806 | + case 1: try { try decoder.decodeSingularStringField(value: &self.metadataAddress) }() | |
| 807 | + case 2: try { try decoder.decodeSingularStringField(value: &self.to) }() | |
| 808 | + case 3: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 809 | + default: break | |
| 810 | + } | |
| 811 | + } | |
| 812 | + } | |
| 813 | + | |
| 814 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 815 | + if !self.metadataAddress.isEmpty { | |
| 816 | + try visitor.visitSingularStringField(value: self.metadataAddress, fieldNumber: 1) | |
| 817 | + } | |
| 818 | + if !self.to.isEmpty { | |
| 819 | + try visitor.visitSingularStringField(value: self.to, fieldNumber: 2) | |
| 820 | + } | |
| 821 | + if self.amount != 0 { | |
| 822 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 3) | |
| 823 | + } | |
| 824 | + try unknownFields.traverse(visitor: &visitor) | |
| 825 | + } | |
| 826 | + | |
| 827 | + public static func ==(lhs: TW_Aptos_Proto_FungibleAssetTransferMessage, rhs: TW_Aptos_Proto_FungibleAssetTransferMessage) -> Bool { | |
| 828 | + if lhs.metadataAddress != rhs.metadataAddress {return false} | |
| 829 | + if lhs.to != rhs.to {return false} | |
| 830 | + if lhs.amount != rhs.amount {return false} | |
| 831 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 832 | + return true | |
| 833 | + } | |
| 834 | +} | |
| 835 | + | |
| 836 | +extension TW_Aptos_Proto_CreateAccountMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 837 | + public static let protoMessageName: String = _protobuf_package + ".CreateAccountMessage" | |
| 838 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 839 | + 1: .standard(proto: "auth_key"), | |
| 840 | + ] | |
| 841 | + | |
| 842 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 843 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 844 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 845 | + // allocates stack space for every case branch when no optimizations are | |
| 846 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 847 | + switch fieldNumber { | |
| 848 | + case 1: try { try decoder.decodeSingularStringField(value: &self.authKey) }() | |
| 849 | + default: break | |
| 850 | + } | |
| 851 | + } | |
| 852 | + } | |
| 853 | + | |
| 854 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 855 | + if !self.authKey.isEmpty { | |
| 856 | + try visitor.visitSingularStringField(value: self.authKey, fieldNumber: 1) | |
| 857 | + } | |
| 858 | + try unknownFields.traverse(visitor: &visitor) | |
| 859 | + } | |
| 860 | + | |
| 861 | + public static func ==(lhs: TW_Aptos_Proto_CreateAccountMessage, rhs: TW_Aptos_Proto_CreateAccountMessage) -> Bool { | |
| 862 | + if lhs.authKey != rhs.authKey {return false} | |
| 863 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 864 | + return true | |
| 865 | + } | |
| 866 | +} | |
| 867 | + | |
| 868 | +extension TW_Aptos_Proto_OfferNftMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 869 | + public static let protoMessageName: String = _protobuf_package + ".OfferNftMessage" | |
| 870 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 871 | + 1: .same(proto: "receiver"), | |
| 872 | + 2: .same(proto: "creator"), | |
| 873 | + 3: .same(proto: "collectionName"), | |
| 874 | + 4: .same(proto: "name"), | |
| 875 | + 5: .standard(proto: "property_version"), | |
| 876 | + 6: .same(proto: "amount"), | |
| 877 | + ] | |
| 878 | + | |
| 879 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 880 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 881 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 882 | + // allocates stack space for every case branch when no optimizations are | |
| 883 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 884 | + switch fieldNumber { | |
| 885 | + case 1: try { try decoder.decodeSingularStringField(value: &self.receiver) }() | |
| 886 | + case 2: try { try decoder.decodeSingularStringField(value: &self.creator) }() | |
| 887 | + case 3: try { try decoder.decodeSingularStringField(value: &self.collectionName) }() | |
| 888 | + case 4: try { try decoder.decodeSingularStringField(value: &self.name) }() | |
| 889 | + case 5: try { try decoder.decodeSingularUInt64Field(value: &self.propertyVersion) }() | |
| 890 | + case 6: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 891 | + default: break | |
| 892 | + } | |
| 893 | + } | |
| 894 | + } | |
| 895 | + | |
| 896 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 897 | + if !self.receiver.isEmpty { | |
| 898 | + try visitor.visitSingularStringField(value: self.receiver, fieldNumber: 1) | |
| 899 | + } | |
| 900 | + if !self.creator.isEmpty { | |
| 901 | + try visitor.visitSingularStringField(value: self.creator, fieldNumber: 2) | |
| 902 | + } | |
| 903 | + if !self.collectionName.isEmpty { | |
| 904 | + try visitor.visitSingularStringField(value: self.collectionName, fieldNumber: 3) | |
| 905 | + } | |
| 906 | + if !self.name.isEmpty { | |
| 907 | + try visitor.visitSingularStringField(value: self.name, fieldNumber: 4) | |
| 908 | + } | |
| 909 | + if self.propertyVersion != 0 { | |
| 910 | + try visitor.visitSingularUInt64Field(value: self.propertyVersion, fieldNumber: 5) | |
| 911 | + } | |
| 912 | + if self.amount != 0 { | |
| 913 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 6) | |
| 914 | + } | |
| 915 | + try unknownFields.traverse(visitor: &visitor) | |
| 916 | + } | |
| 917 | + | |
| 918 | + public static func ==(lhs: TW_Aptos_Proto_OfferNftMessage, rhs: TW_Aptos_Proto_OfferNftMessage) -> Bool { | |
| 919 | + if lhs.receiver != rhs.receiver {return false} | |
| 920 | + if lhs.creator != rhs.creator {return false} | |
| 921 | + if lhs.collectionName != rhs.collectionName {return false} | |
| 922 | + if lhs.name != rhs.name {return false} | |
| 923 | + if lhs.propertyVersion != rhs.propertyVersion {return false} | |
| 924 | + if lhs.amount != rhs.amount {return false} | |
| 925 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 926 | + return true | |
| 927 | + } | |
| 928 | +} | |
| 929 | + | |
| 930 | +extension TW_Aptos_Proto_CancelOfferNftMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 931 | + public static let protoMessageName: String = _protobuf_package + ".CancelOfferNftMessage" | |
| 932 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 933 | + 1: .same(proto: "receiver"), | |
| 934 | + 2: .same(proto: "creator"), | |
| 935 | + 3: .same(proto: "collectionName"), | |
| 936 | + 4: .same(proto: "name"), | |
| 937 | + 5: .standard(proto: "property_version"), | |
| 938 | + ] | |
| 939 | + | |
| 940 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 941 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 942 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 943 | + // allocates stack space for every case branch when no optimizations are | |
| 944 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 945 | + switch fieldNumber { | |
| 946 | + case 1: try { try decoder.decodeSingularStringField(value: &self.receiver) }() | |
| 947 | + case 2: try { try decoder.decodeSingularStringField(value: &self.creator) }() | |
| 948 | + case 3: try { try decoder.decodeSingularStringField(value: &self.collectionName) }() | |
| 949 | + case 4: try { try decoder.decodeSingularStringField(value: &self.name) }() | |
| 950 | + case 5: try { try decoder.decodeSingularUInt64Field(value: &self.propertyVersion) }() | |
| 951 | + default: break | |
| 952 | + } | |
| 953 | + } | |
| 954 | + } | |
| 955 | + | |
| 956 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 957 | + if !self.receiver.isEmpty { | |
| 958 | + try visitor.visitSingularStringField(value: self.receiver, fieldNumber: 1) | |
| 959 | + } | |
| 960 | + if !self.creator.isEmpty { | |
| 961 | + try visitor.visitSingularStringField(value: self.creator, fieldNumber: 2) | |
| 962 | + } | |
| 963 | + if !self.collectionName.isEmpty { | |
| 964 | + try visitor.visitSingularStringField(value: self.collectionName, fieldNumber: 3) | |
| 965 | + } | |
| 966 | + if !self.name.isEmpty { | |
| 967 | + try visitor.visitSingularStringField(value: self.name, fieldNumber: 4) | |
| 968 | + } | |
| 969 | + if self.propertyVersion != 0 { | |
| 970 | + try visitor.visitSingularUInt64Field(value: self.propertyVersion, fieldNumber: 5) | |
| 971 | + } | |
| 972 | + try unknownFields.traverse(visitor: &visitor) | |
| 973 | + } | |
| 974 | + | |
| 975 | + public static func ==(lhs: TW_Aptos_Proto_CancelOfferNftMessage, rhs: TW_Aptos_Proto_CancelOfferNftMessage) -> Bool { | |
| 976 | + if lhs.receiver != rhs.receiver {return false} | |
| 977 | + if lhs.creator != rhs.creator {return false} | |
| 978 | + if lhs.collectionName != rhs.collectionName {return false} | |
| 979 | + if lhs.name != rhs.name {return false} | |
| 980 | + if lhs.propertyVersion != rhs.propertyVersion {return false} | |
| 981 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 982 | + return true | |
| 983 | + } | |
| 984 | +} | |
| 985 | + | |
| 986 | +extension TW_Aptos_Proto_ClaimNftMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 987 | + public static let protoMessageName: String = _protobuf_package + ".ClaimNftMessage" | |
| 988 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 989 | + 1: .same(proto: "sender"), | |
| 990 | + 2: .same(proto: "creator"), | |
| 991 | + 3: .same(proto: "collectionName"), | |
| 992 | + 4: .same(proto: "name"), | |
| 993 | + 5: .standard(proto: "property_version"), | |
| 994 | + ] | |
| 995 | + | |
| 996 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 997 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 998 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 999 | + // allocates stack space for every case branch when no optimizations are | |
| 1000 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1001 | + switch fieldNumber { | |
| 1002 | + case 1: try { try decoder.decodeSingularStringField(value: &self.sender) }() | |
| 1003 | + case 2: try { try decoder.decodeSingularStringField(value: &self.creator) }() | |
| 1004 | + case 3: try { try decoder.decodeSingularStringField(value: &self.collectionName) }() | |
| 1005 | + case 4: try { try decoder.decodeSingularStringField(value: &self.name) }() | |
| 1006 | + case 5: try { try decoder.decodeSingularUInt64Field(value: &self.propertyVersion) }() | |
| 1007 | + default: break | |
| 1008 | + } | |
| 1009 | + } | |
| 1010 | + } | |
| 1011 | + | |
| 1012 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1013 | + if !self.sender.isEmpty { | |
| 1014 | + try visitor.visitSingularStringField(value: self.sender, fieldNumber: 1) | |
| 1015 | + } | |
| 1016 | + if !self.creator.isEmpty { | |
| 1017 | + try visitor.visitSingularStringField(value: self.creator, fieldNumber: 2) | |
| 1018 | + } | |
| 1019 | + if !self.collectionName.isEmpty { | |
| 1020 | + try visitor.visitSingularStringField(value: self.collectionName, fieldNumber: 3) | |
| 1021 | + } | |
| 1022 | + if !self.name.isEmpty { | |
| 1023 | + try visitor.visitSingularStringField(value: self.name, fieldNumber: 4) | |
| 1024 | + } | |
| 1025 | + if self.propertyVersion != 0 { | |
| 1026 | + try visitor.visitSingularUInt64Field(value: self.propertyVersion, fieldNumber: 5) | |
| 1027 | + } | |
| 1028 | + try unknownFields.traverse(visitor: &visitor) | |
| 1029 | + } | |
| 1030 | + | |
| 1031 | + public static func ==(lhs: TW_Aptos_Proto_ClaimNftMessage, rhs: TW_Aptos_Proto_ClaimNftMessage) -> Bool { | |
| 1032 | + if lhs.sender != rhs.sender {return false} | |
| 1033 | + if lhs.creator != rhs.creator {return false} | |
| 1034 | + if lhs.collectionName != rhs.collectionName {return false} | |
| 1035 | + if lhs.name != rhs.name {return false} | |
| 1036 | + if lhs.propertyVersion != rhs.propertyVersion {return false} | |
| 1037 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1038 | + return true | |
| 1039 | + } | |
| 1040 | +} | |
| 1041 | + | |
| 1042 | +extension TW_Aptos_Proto_TortugaClaim: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1043 | + public static let protoMessageName: String = _protobuf_package + ".TortugaClaim" | |
| 1044 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1045 | + 1: .same(proto: "idx"), | |
| 1046 | + ] | |
| 1047 | + | |
| 1048 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1049 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1050 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1051 | + // allocates stack space for every case branch when no optimizations are | |
| 1052 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1053 | + switch fieldNumber { | |
| 1054 | + case 1: try { try decoder.decodeSingularUInt64Field(value: &self.idx) }() | |
| 1055 | + default: break | |
| 1056 | + } | |
| 1057 | + } | |
| 1058 | + } | |
| 1059 | + | |
| 1060 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1061 | + if self.idx != 0 { | |
| 1062 | + try visitor.visitSingularUInt64Field(value: self.idx, fieldNumber: 1) | |
| 1063 | + } | |
| 1064 | + try unknownFields.traverse(visitor: &visitor) | |
| 1065 | + } | |
| 1066 | + | |
| 1067 | + public static func ==(lhs: TW_Aptos_Proto_TortugaClaim, rhs: TW_Aptos_Proto_TortugaClaim) -> Bool { | |
| 1068 | + if lhs.idx != rhs.idx {return false} | |
| 1069 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1070 | + return true | |
| 1071 | + } | |
| 1072 | +} | |
| 1073 | + | |
| 1074 | +extension TW_Aptos_Proto_TortugaStake: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1075 | + public static let protoMessageName: String = _protobuf_package + ".TortugaStake" | |
| 1076 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1077 | + 1: .same(proto: "amount"), | |
| 1078 | + ] | |
| 1079 | + | |
| 1080 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1081 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1082 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1083 | + // allocates stack space for every case branch when no optimizations are | |
| 1084 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1085 | + switch fieldNumber { | |
| 1086 | + case 1: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 1087 | + default: break | |
| 1088 | + } | |
| 1089 | + } | |
| 1090 | + } | |
| 1091 | + | |
| 1092 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1093 | + if self.amount != 0 { | |
| 1094 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 1) | |
| 1095 | + } | |
| 1096 | + try unknownFields.traverse(visitor: &visitor) | |
| 1097 | + } | |
| 1098 | + | |
| 1099 | + public static func ==(lhs: TW_Aptos_Proto_TortugaStake, rhs: TW_Aptos_Proto_TortugaStake) -> Bool { | |
| 1100 | + if lhs.amount != rhs.amount {return false} | |
| 1101 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1102 | + return true | |
| 1103 | + } | |
| 1104 | +} | |
| 1105 | + | |
| 1106 | +extension TW_Aptos_Proto_TortugaUnstake: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1107 | + public static let protoMessageName: String = _protobuf_package + ".TortugaUnstake" | |
| 1108 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1109 | + 1: .same(proto: "amount"), | |
| 1110 | + ] | |
| 1111 | + | |
| 1112 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1113 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1114 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1115 | + // allocates stack space for every case branch when no optimizations are | |
| 1116 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1117 | + switch fieldNumber { | |
| 1118 | + case 1: try { try decoder.decodeSingularUInt64Field(value: &self.amount) }() | |
| 1119 | + default: break | |
| 1120 | + } | |
| 1121 | + } | |
| 1122 | + } | |
| 1123 | + | |
| 1124 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1125 | + if self.amount != 0 { | |
| 1126 | + try visitor.visitSingularUInt64Field(value: self.amount, fieldNumber: 1) | |
| 1127 | + } | |
| 1128 | + try unknownFields.traverse(visitor: &visitor) | |
| 1129 | + } | |
| 1130 | + | |
| 1131 | + public static func ==(lhs: TW_Aptos_Proto_TortugaUnstake, rhs: TW_Aptos_Proto_TortugaUnstake) -> Bool { | |
| 1132 | + if lhs.amount != rhs.amount {return false} | |
| 1133 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1134 | + return true | |
| 1135 | + } | |
| 1136 | +} | |
| 1137 | + | |
| 1138 | +extension TW_Aptos_Proto_LiquidStaking: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1139 | + public static let protoMessageName: String = _protobuf_package + ".LiquidStaking" | |
| 1140 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1141 | + 1: .standard(proto: "smart_contract_address"), | |
| 1142 | + 2: .same(proto: "stake"), | |
| 1143 | + 3: .same(proto: "unstake"), | |
| 1144 | + 4: .same(proto: "claim"), | |
| 1145 | + ] | |
| 1146 | + | |
| 1147 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1148 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1149 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1150 | + // allocates stack space for every case branch when no optimizations are | |
| 1151 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1152 | + switch fieldNumber { | |
| 1153 | + case 1: try { try decoder.decodeSingularStringField(value: &self.smartContractAddress) }() | |
| 1154 | + case 2: try { | |
| 1155 | + var v: TW_Aptos_Proto_TortugaStake? | |
| 1156 | + var hadOneofValue = false | |
| 1157 | + if let current = self.liquidStakeTransactionPayload { | |
| 1158 | + hadOneofValue = true | |
| 1159 | + if case .stake(let m) = current {v = m} | |
| 1160 | + } | |
| 1161 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1162 | + if let v = v { | |
| 1163 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1164 | + self.liquidStakeTransactionPayload = .stake(v) | |
| 1165 | + } | |
| 1166 | + }() | |
| 1167 | + case 3: try { | |
| 1168 | + var v: TW_Aptos_Proto_TortugaUnstake? | |
| 1169 | + var hadOneofValue = false | |
| 1170 | + if let current = self.liquidStakeTransactionPayload { | |
| 1171 | + hadOneofValue = true | |
| 1172 | + if case .unstake(let m) = current {v = m} | |
| 1173 | + } | |
| 1174 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1175 | + if let v = v { | |
| 1176 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1177 | + self.liquidStakeTransactionPayload = .unstake(v) | |
| 1178 | + } | |
| 1179 | + }() | |
| 1180 | + case 4: try { | |
| 1181 | + var v: TW_Aptos_Proto_TortugaClaim? | |
| 1182 | + var hadOneofValue = false | |
| 1183 | + if let current = self.liquidStakeTransactionPayload { | |
| 1184 | + hadOneofValue = true | |
| 1185 | + if case .claim(let m) = current {v = m} | |
| 1186 | + } | |
| 1187 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1188 | + if let v = v { | |
| 1189 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1190 | + self.liquidStakeTransactionPayload = .claim(v) | |
| 1191 | + } | |
| 1192 | + }() | |
| 1193 | + default: break | |
| 1194 | + } | |
| 1195 | + } | |
| 1196 | + } | |
| 1197 | + | |
| 1198 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1199 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1200 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1201 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1202 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1203 | + if !self.smartContractAddress.isEmpty { | |
| 1204 | + try visitor.visitSingularStringField(value: self.smartContractAddress, fieldNumber: 1) | |
| 1205 | + } | |
| 1206 | + switch self.liquidStakeTransactionPayload { | |
| 1207 | + case .stake?: try { | |
| 1208 | + guard case .stake(let v)? = self.liquidStakeTransactionPayload else { preconditionFailure() } | |
| 1209 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) | |
| 1210 | + }() | |
| 1211 | + case .unstake?: try { | |
| 1212 | + guard case .unstake(let v)? = self.liquidStakeTransactionPayload else { preconditionFailure() } | |
| 1213 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) | |
| 1214 | + }() | |
| 1215 | + case .claim?: try { | |
| 1216 | + guard case .claim(let v)? = self.liquidStakeTransactionPayload else { preconditionFailure() } | |
| 1217 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) | |
| 1218 | + }() | |
| 1219 | + case nil: break | |
| 1220 | + } | |
| 1221 | + try unknownFields.traverse(visitor: &visitor) | |
| 1222 | + } | |
| 1223 | + | |
| 1224 | + public static func ==(lhs: TW_Aptos_Proto_LiquidStaking, rhs: TW_Aptos_Proto_LiquidStaking) -> Bool { | |
| 1225 | + if lhs.smartContractAddress != rhs.smartContractAddress {return false} | |
| 1226 | + if lhs.liquidStakeTransactionPayload != rhs.liquidStakeTransactionPayload {return false} | |
| 1227 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1228 | + return true | |
| 1229 | + } | |
| 1230 | +} | |
| 1231 | + | |
| 1232 | +extension TW_Aptos_Proto_NftMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1233 | + public static let protoMessageName: String = _protobuf_package + ".NftMessage" | |
| 1234 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1235 | + 1: .standard(proto: "offer_nft"), | |
| 1236 | + 2: .standard(proto: "cancel_offer_nft"), | |
| 1237 | + 3: .standard(proto: "claim_nft"), | |
| 1238 | + ] | |
| 1239 | + | |
| 1240 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1241 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1242 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1243 | + // allocates stack space for every case branch when no optimizations are | |
| 1244 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1245 | + switch fieldNumber { | |
| 1246 | + case 1: try { | |
| 1247 | + var v: TW_Aptos_Proto_OfferNftMessage? | |
| 1248 | + var hadOneofValue = false | |
| 1249 | + if let current = self.nftTransactionPayload { | |
| 1250 | + hadOneofValue = true | |
| 1251 | + if case .offerNft(let m) = current {v = m} | |
| 1252 | + } | |
| 1253 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1254 | + if let v = v { | |
| 1255 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1256 | + self.nftTransactionPayload = .offerNft(v) | |
| 1257 | + } | |
| 1258 | + }() | |
| 1259 | + case 2: try { | |
| 1260 | + var v: TW_Aptos_Proto_CancelOfferNftMessage? | |
| 1261 | + var hadOneofValue = false | |
| 1262 | + if let current = self.nftTransactionPayload { | |
| 1263 | + hadOneofValue = true | |
| 1264 | + if case .cancelOfferNft(let m) = current {v = m} | |
| 1265 | + } | |
| 1266 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1267 | + if let v = v { | |
| 1268 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1269 | + self.nftTransactionPayload = .cancelOfferNft(v) | |
| 1270 | + } | |
| 1271 | + }() | |
| 1272 | + case 3: try { | |
| 1273 | + var v: TW_Aptos_Proto_ClaimNftMessage? | |
| 1274 | + var hadOneofValue = false | |
| 1275 | + if let current = self.nftTransactionPayload { | |
| 1276 | + hadOneofValue = true | |
| 1277 | + if case .claimNft(let m) = current {v = m} | |
| 1278 | + } | |
| 1279 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1280 | + if let v = v { | |
| 1281 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1282 | + self.nftTransactionPayload = .claimNft(v) | |
| 1283 | + } | |
| 1284 | + }() | |
| 1285 | + default: break | |
| 1286 | + } | |
| 1287 | + } | |
| 1288 | + } | |
| 1289 | + | |
| 1290 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1291 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1292 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1293 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1294 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1295 | + switch self.nftTransactionPayload { | |
| 1296 | + case .offerNft?: try { | |
| 1297 | + guard case .offerNft(let v)? = self.nftTransactionPayload else { preconditionFailure() } | |
| 1298 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 1299 | + }() | |
| 1300 | + case .cancelOfferNft?: try { | |
| 1301 | + guard case .cancelOfferNft(let v)? = self.nftTransactionPayload else { preconditionFailure() } | |
| 1302 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) | |
| 1303 | + }() | |
| 1304 | + case .claimNft?: try { | |
| 1305 | + guard case .claimNft(let v)? = self.nftTransactionPayload else { preconditionFailure() } | |
| 1306 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) | |
| 1307 | + }() | |
| 1308 | + case nil: break | |
| 1309 | + } | |
| 1310 | + try unknownFields.traverse(visitor: &visitor) | |
| 1311 | + } | |
| 1312 | + | |
| 1313 | + public static func ==(lhs: TW_Aptos_Proto_NftMessage, rhs: TW_Aptos_Proto_NftMessage) -> Bool { | |
| 1314 | + if lhs.nftTransactionPayload != rhs.nftTransactionPayload {return false} | |
| 1315 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1316 | + return true | |
| 1317 | + } | |
| 1318 | +} | |
| 1319 | + | |
| 1320 | +extension TW_Aptos_Proto_SigningInput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1321 | + public static let protoMessageName: String = _protobuf_package + ".SigningInput" | |
| 1322 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1323 | + 1: .same(proto: "sender"), | |
| 1324 | + 2: .standard(proto: "sequence_number"), | |
| 1325 | + 3: .standard(proto: "max_gas_amount"), | |
| 1326 | + 4: .standard(proto: "gas_unit_price"), | |
| 1327 | + 5: .standard(proto: "expiration_timestamp_secs"), | |
| 1328 | + 6: .standard(proto: "chain_id"), | |
| 1329 | + 7: .standard(proto: "private_key"), | |
| 1330 | + 8: .standard(proto: "any_encoded"), | |
| 1331 | + 9: .same(proto: "transfer"), | |
| 1332 | + 10: .standard(proto: "token_transfer"), | |
| 1333 | + 11: .standard(proto: "create_account"), | |
| 1334 | + 12: .standard(proto: "nft_message"), | |
| 1335 | + 14: .standard(proto: "liquid_staking_message"), | |
| 1336 | + 15: .standard(proto: "token_transfer_coins"), | |
| 1337 | + 16: .standard(proto: "fungible_asset_transfer"), | |
| 1338 | + 21: .same(proto: "abi"), | |
| 1339 | + ] | |
| 1340 | + | |
| 1341 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1342 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1343 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1344 | + // allocates stack space for every case branch when no optimizations are | |
| 1345 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1346 | + switch fieldNumber { | |
| 1347 | + case 1: try { try decoder.decodeSingularStringField(value: &self.sender) }() | |
| 1348 | + case 2: try { try decoder.decodeSingularInt64Field(value: &self.sequenceNumber) }() | |
| 1349 | + case 3: try { try decoder.decodeSingularUInt64Field(value: &self.maxGasAmount) }() | |
| 1350 | + case 4: try { try decoder.decodeSingularUInt64Field(value: &self.gasUnitPrice) }() | |
| 1351 | + case 5: try { try decoder.decodeSingularUInt64Field(value: &self.expirationTimestampSecs) }() | |
| 1352 | + case 6: try { try decoder.decodeSingularUInt32Field(value: &self.chainID) }() | |
| 1353 | + case 7: try { try decoder.decodeSingularBytesField(value: &self.privateKey) }() | |
| 1354 | + case 8: try { try decoder.decodeSingularStringField(value: &self.anyEncoded) }() | |
| 1355 | + case 9: try { | |
| 1356 | + var v: TW_Aptos_Proto_TransferMessage? | |
| 1357 | + var hadOneofValue = false | |
| 1358 | + if let current = self.transactionPayload { | |
| 1359 | + hadOneofValue = true | |
| 1360 | + if case .transfer(let m) = current {v = m} | |
| 1361 | + } | |
| 1362 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1363 | + if let v = v { | |
| 1364 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1365 | + self.transactionPayload = .transfer(v) | |
| 1366 | + } | |
| 1367 | + }() | |
| 1368 | + case 10: try { | |
| 1369 | + var v: TW_Aptos_Proto_TokenTransferMessage? | |
| 1370 | + var hadOneofValue = false | |
| 1371 | + if let current = self.transactionPayload { | |
| 1372 | + hadOneofValue = true | |
| 1373 | + if case .tokenTransfer(let m) = current {v = m} | |
| 1374 | + } | |
| 1375 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1376 | + if let v = v { | |
| 1377 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1378 | + self.transactionPayload = .tokenTransfer(v) | |
| 1379 | + } | |
| 1380 | + }() | |
| 1381 | + case 11: try { | |
| 1382 | + var v: TW_Aptos_Proto_CreateAccountMessage? | |
| 1383 | + var hadOneofValue = false | |
| 1384 | + if let current = self.transactionPayload { | |
| 1385 | + hadOneofValue = true | |
| 1386 | + if case .createAccount(let m) = current {v = m} | |
| 1387 | + } | |
| 1388 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1389 | + if let v = v { | |
| 1390 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1391 | + self.transactionPayload = .createAccount(v) | |
| 1392 | + } | |
| 1393 | + }() | |
| 1394 | + case 12: try { | |
| 1395 | + var v: TW_Aptos_Proto_NftMessage? | |
| 1396 | + var hadOneofValue = false | |
| 1397 | + if let current = self.transactionPayload { | |
| 1398 | + hadOneofValue = true | |
| 1399 | + if case .nftMessage(let m) = current {v = m} | |
| 1400 | + } | |
| 1401 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1402 | + if let v = v { | |
| 1403 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1404 | + self.transactionPayload = .nftMessage(v) | |
| 1405 | + } | |
| 1406 | + }() | |
| 1407 | + case 14: try { | |
| 1408 | + var v: TW_Aptos_Proto_LiquidStaking? | |
| 1409 | + var hadOneofValue = false | |
| 1410 | + if let current = self.transactionPayload { | |
| 1411 | + hadOneofValue = true | |
| 1412 | + if case .liquidStakingMessage(let m) = current {v = m} | |
| 1413 | + } | |
| 1414 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1415 | + if let v = v { | |
| 1416 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1417 | + self.transactionPayload = .liquidStakingMessage(v) | |
| 1418 | + } | |
| 1419 | + }() | |
| 1420 | + case 15: try { | |
| 1421 | + var v: TW_Aptos_Proto_TokenTransferCoinsMessage? | |
| 1422 | + var hadOneofValue = false | |
| 1423 | + if let current = self.transactionPayload { | |
| 1424 | + hadOneofValue = true | |
| 1425 | + if case .tokenTransferCoins(let m) = current {v = m} | |
| 1426 | + } | |
| 1427 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1428 | + if let v = v { | |
| 1429 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1430 | + self.transactionPayload = .tokenTransferCoins(v) | |
| 1431 | + } | |
| 1432 | + }() | |
| 1433 | + case 16: try { | |
| 1434 | + var v: TW_Aptos_Proto_FungibleAssetTransferMessage? | |
| 1435 | + var hadOneofValue = false | |
| 1436 | + if let current = self.transactionPayload { | |
| 1437 | + hadOneofValue = true | |
| 1438 | + if case .fungibleAssetTransfer(let m) = current {v = m} | |
| 1439 | + } | |
| 1440 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1441 | + if let v = v { | |
| 1442 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1443 | + self.transactionPayload = .fungibleAssetTransfer(v) | |
| 1444 | + } | |
| 1445 | + }() | |
| 1446 | + case 21: try { try decoder.decodeSingularStringField(value: &self.abi) }() | |
| 1447 | + default: break | |
| 1448 | + } | |
| 1449 | + } | |
| 1450 | + } | |
| 1451 | + | |
| 1452 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1453 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1454 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1455 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1456 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1457 | + if !self.sender.isEmpty { | |
| 1458 | + try visitor.visitSingularStringField(value: self.sender, fieldNumber: 1) | |
| 1459 | + } | |
| 1460 | + if self.sequenceNumber != 0 { | |
| 1461 | + try visitor.visitSingularInt64Field(value: self.sequenceNumber, fieldNumber: 2) | |
| 1462 | + } | |
| 1463 | + if self.maxGasAmount != 0 { | |
| 1464 | + try visitor.visitSingularUInt64Field(value: self.maxGasAmount, fieldNumber: 3) | |
| 1465 | + } | |
| 1466 | + if self.gasUnitPrice != 0 { | |
| 1467 | + try visitor.visitSingularUInt64Field(value: self.gasUnitPrice, fieldNumber: 4) | |
| 1468 | + } | |
| 1469 | + if self.expirationTimestampSecs != 0 { | |
| 1470 | + try visitor.visitSingularUInt64Field(value: self.expirationTimestampSecs, fieldNumber: 5) | |
| 1471 | + } | |
| 1472 | + if self.chainID != 0 { | |
| 1473 | + try visitor.visitSingularUInt32Field(value: self.chainID, fieldNumber: 6) | |
| 1474 | + } | |
| 1475 | + if !self.privateKey.isEmpty { | |
| 1476 | + try visitor.visitSingularBytesField(value: self.privateKey, fieldNumber: 7) | |
| 1477 | + } | |
| 1478 | + if !self.anyEncoded.isEmpty { | |
| 1479 | + try visitor.visitSingularStringField(value: self.anyEncoded, fieldNumber: 8) | |
| 1480 | + } | |
| 1481 | + switch self.transactionPayload { | |
| 1482 | + case .transfer?: try { | |
| 1483 | + guard case .transfer(let v)? = self.transactionPayload else { preconditionFailure() } | |
| 1484 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 9) | |
| 1485 | + }() | |
| 1486 | + case .tokenTransfer?: try { | |
| 1487 | + guard case .tokenTransfer(let v)? = self.transactionPayload else { preconditionFailure() } | |
| 1488 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 10) | |
| 1489 | + }() | |
| 1490 | + case .createAccount?: try { | |
| 1491 | + guard case .createAccount(let v)? = self.transactionPayload else { preconditionFailure() } | |
| 1492 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 11) | |
| 1493 | + }() | |
| 1494 | + case .nftMessage?: try { | |
| 1495 | + guard case .nftMessage(let v)? = self.transactionPayload else { preconditionFailure() } | |
| 1496 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 12) | |
| 1497 | + }() | |
| 1498 | + case .liquidStakingMessage?: try { | |
| 1499 | + guard case .liquidStakingMessage(let v)? = self.transactionPayload else { preconditionFailure() } | |
| 1500 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 14) | |
| 1501 | + }() | |
| 1502 | + case .tokenTransferCoins?: try { | |
| 1503 | + guard case .tokenTransferCoins(let v)? = self.transactionPayload else { preconditionFailure() } | |
| 1504 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 15) | |
| 1505 | + }() | |
| 1506 | + case .fungibleAssetTransfer?: try { | |
| 1507 | + guard case .fungibleAssetTransfer(let v)? = self.transactionPayload else { preconditionFailure() } | |
| 1508 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 16) | |
| 1509 | + }() | |
| 1510 | + case nil: break | |
| 1511 | + } | |
| 1512 | + if !self.abi.isEmpty { | |
| 1513 | + try visitor.visitSingularStringField(value: self.abi, fieldNumber: 21) | |
| 1514 | + } | |
| 1515 | + try unknownFields.traverse(visitor: &visitor) | |
| 1516 | + } | |
| 1517 | + | |
| 1518 | + public static func ==(lhs: TW_Aptos_Proto_SigningInput, rhs: TW_Aptos_Proto_SigningInput) -> Bool { | |
| 1519 | + if lhs.sender != rhs.sender {return false} | |
| 1520 | + if lhs.sequenceNumber != rhs.sequenceNumber {return false} | |
| 1521 | + if lhs.maxGasAmount != rhs.maxGasAmount {return false} | |
| 1522 | + if lhs.gasUnitPrice != rhs.gasUnitPrice {return false} | |
| 1523 | + if lhs.expirationTimestampSecs != rhs.expirationTimestampSecs {return false} | |
| 1524 | + if lhs.chainID != rhs.chainID {return false} | |
| 1525 | + if lhs.privateKey != rhs.privateKey {return false} | |
| 1526 | + if lhs.anyEncoded != rhs.anyEncoded {return false} | |
| 1527 | + if lhs.transactionPayload != rhs.transactionPayload {return false} | |
| 1528 | + if lhs.abi != rhs.abi {return false} | |
| 1529 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1530 | + return true | |
| 1531 | + } | |
| 1532 | +} | |
| 1533 | + | |
| 1534 | +extension TW_Aptos_Proto_TransactionAuthenticator: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1535 | + public static let protoMessageName: String = _protobuf_package + ".TransactionAuthenticator" | |
| 1536 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1537 | + 1: .same(proto: "signature"), | |
| 1538 | + 2: .standard(proto: "public_key"), | |
| 1539 | + ] | |
| 1540 | + | |
| 1541 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1542 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1543 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1544 | + // allocates stack space for every case branch when no optimizations are | |
| 1545 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1546 | + switch fieldNumber { | |
| 1547 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.signature) }() | |
| 1548 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.publicKey) }() | |
| 1549 | + default: break | |
| 1550 | + } | |
| 1551 | + } | |
| 1552 | + } | |
| 1553 | + | |
| 1554 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1555 | + if !self.signature.isEmpty { | |
| 1556 | + try visitor.visitSingularBytesField(value: self.signature, fieldNumber: 1) | |
| 1557 | + } | |
| 1558 | + if !self.publicKey.isEmpty { | |
| 1559 | + try visitor.visitSingularBytesField(value: self.publicKey, fieldNumber: 2) | |
| 1560 | + } | |
| 1561 | + try unknownFields.traverse(visitor: &visitor) | |
| 1562 | + } | |
| 1563 | + | |
| 1564 | + public static func ==(lhs: TW_Aptos_Proto_TransactionAuthenticator, rhs: TW_Aptos_Proto_TransactionAuthenticator) -> Bool { | |
| 1565 | + if lhs.signature != rhs.signature {return false} | |
| 1566 | + if lhs.publicKey != rhs.publicKey {return false} | |
| 1567 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1568 | + return true | |
| 1569 | + } | |
| 1570 | +} | |
| 1571 | + | |
| 1572 | +extension TW_Aptos_Proto_SigningOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1573 | + public static let protoMessageName: String = _protobuf_package + ".SigningOutput" | |
| 1574 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1575 | + 1: .standard(proto: "raw_txn"), | |
| 1576 | + 2: .same(proto: "authenticator"), | |
| 1577 | + 3: .same(proto: "encoded"), | |
| 1578 | + 4: .same(proto: "json"), | |
| 1579 | + 5: .same(proto: "error"), | |
| 1580 | + 6: .standard(proto: "error_message"), | |
| 1581 | + ] | |
| 1582 | + | |
| 1583 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1584 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1585 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1586 | + // allocates stack space for every case branch when no optimizations are | |
| 1587 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1588 | + switch fieldNumber { | |
| 1589 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.rawTxn) }() | |
| 1590 | + case 2: try { try decoder.decodeSingularMessageField(value: &self._authenticator) }() | |
| 1591 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.encoded) }() | |
| 1592 | + case 4: try { try decoder.decodeSingularStringField(value: &self.json) }() | |
| 1593 | + case 5: try { try decoder.decodeSingularEnumField(value: &self.error) }() | |
| 1594 | + case 6: try { try decoder.decodeSingularStringField(value: &self.errorMessage) }() | |
| 1595 | + default: break | |
| 1596 | + } | |
| 1597 | + } | |
| 1598 | + } | |
| 1599 | + | |
| 1600 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1601 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1602 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1603 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1604 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1605 | + if !self.rawTxn.isEmpty { | |
| 1606 | + try visitor.visitSingularBytesField(value: self.rawTxn, fieldNumber: 1) | |
| 1607 | + } | |
| 1608 | + try { if let v = self._authenticator { | |
| 1609 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) | |
| 1610 | + } }() | |
| 1611 | + if !self.encoded.isEmpty { | |
| 1612 | + try visitor.visitSingularBytesField(value: self.encoded, fieldNumber: 3) | |
| 1613 | + } | |
| 1614 | + if !self.json.isEmpty { | |
| 1615 | + try visitor.visitSingularStringField(value: self.json, fieldNumber: 4) | |
| 1616 | + } | |
| 1617 | + if self.error != .ok { | |
| 1618 | + try visitor.visitSingularEnumField(value: self.error, fieldNumber: 5) | |
| 1619 | + } | |
| 1620 | + if !self.errorMessage.isEmpty { | |
| 1621 | + try visitor.visitSingularStringField(value: self.errorMessage, fieldNumber: 6) | |
| 1622 | + } | |
| 1623 | + try unknownFields.traverse(visitor: &visitor) | |
| 1624 | + } | |
| 1625 | + | |
| 1626 | + public static func ==(lhs: TW_Aptos_Proto_SigningOutput, rhs: TW_Aptos_Proto_SigningOutput) -> Bool { | |
| 1627 | + if lhs.rawTxn != rhs.rawTxn {return false} | |
| 1628 | + if lhs._authenticator != rhs._authenticator {return false} | |
| 1629 | + if lhs.encoded != rhs.encoded {return false} | |
| 1630 | + if lhs.json != rhs.json {return false} | |
| 1631 | + if lhs.error != rhs.error {return false} | |
| 1632 | + if lhs.errorMessage != rhs.errorMessage {return false} | |
| 1633 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1634 | + return true | |
| 1635 | + } | |
| 1636 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/BabylonStaking+Proto.swift
+10 −0
@@ -0,0 +1,10 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public typealias BabylonStakingPublicKeySignature = TW_BabylonStaking_Proto_PublicKeySignature | |
| 8 | +public typealias BabylonStakingStakingInfo = TW_BabylonStaking_Proto_StakingInfo | |
| 9 | +public typealias BabylonStakingInputBuilder = TW_BabylonStaking_Proto_InputBuilder | |
| 10 | +public typealias BabylonStakingOutputBuilder = TW_BabylonStaking_Proto_OutputBuilder | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/BabylonStaking.pb.swift
+755 −0
@@ -0,0 +1,755 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// DO NOT EDIT. | |
| 4 | +// swift-format-ignore-file | |
| 5 | +// | |
| 6 | +// Generated by the Swift generator plugin for the protocol buffer compiler. | |
| 7 | +// Source: BabylonStaking.proto | |
| 8 | +// | |
| 9 | +// For information on using the generated types, please see the documentation: | |
| 10 | +// https://github.com/apple/swift-protobuf/ | |
| 11 | + | |
| 12 | +import Foundation | |
| 13 | +import SwiftProtobuf | |
| 14 | + | |
| 15 | +// If the compiler emits an error on this type, it is because this file | |
| 16 | +// was generated by a version of the `protoc` Swift plug-in that is | |
| 17 | +// incompatible with the version of SwiftProtobuf.to which you are linking. | |
| 18 | +// Please ensure that you are building against the same version of the API | |
| 19 | +// that was used to generate this file. | |
| 20 | +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { | |
| 21 | + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} | |
| 22 | + typealias Version = _2 | |
| 23 | +} | |
| 24 | + | |
| 25 | +/// Public key and corresponding signature. | |
| 26 | +public struct TW_BabylonStaking_Proto_PublicKeySignature { | |
| 27 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 28 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 29 | + // methods supported on all messages. | |
| 30 | + | |
| 31 | + /// Public key bytes. Can be either compressed (33 bytes) or x-only (32 bytes). | |
| 32 | + public var publicKey: Data = Data() | |
| 33 | + | |
| 34 | + /// Signature 64-length byte array. | |
| 35 | + public var signature: Data = Data() | |
| 36 | + | |
| 37 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 38 | + | |
| 39 | + public init() {} | |
| 40 | +} | |
| 41 | + | |
| 42 | +public struct TW_BabylonStaking_Proto_StakingInfo { | |
| 43 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 44 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 45 | + // methods supported on all messages. | |
| 46 | + | |
| 47 | + /// User's public key. | |
| 48 | + public var stakerPublicKey: Data = Data() | |
| 49 | + | |
| 50 | + /// Finality provider's public key chosen by the user. | |
| 51 | + public var finalityProviderPublicKey: Data = Data() | |
| 52 | + | |
| 53 | + /// Staking Output's lock time. | |
| 54 | + /// Equal to `global_parameters.staking_time` when creating a Staking transaction. | |
| 55 | + /// or `global_parameters.unbonding_time` when creating an Unbonding transaction. | |
| 56 | + public var stakingTime: UInt32 = 0 | |
| 57 | + | |
| 58 | + /// Retrieved from global_parameters.covenant_pks. | |
| 59 | + /// Babylon nodes that can approve Unbonding tx or Slash the staked position when acting bad. | |
| 60 | + public var covenantCommitteePublicKeys: [Data] = [] | |
| 61 | + | |
| 62 | + /// Retrieved from global_parameters.covenant_quorum. | |
| 63 | + /// Specifies the quorum required by the covenant committee for unbonding transactions to be confirmed. | |
| 64 | + public var covenantQuorum: UInt32 = 0 | |
| 65 | + | |
| 66 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 67 | + | |
| 68 | + public init() {} | |
| 69 | +} | |
| 70 | + | |
| 71 | +public struct TW_BabylonStaking_Proto_InputBuilder { | |
| 72 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 73 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 74 | + // methods supported on all messages. | |
| 75 | + | |
| 76 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 77 | + | |
| 78 | + /// Spend a Staking Output via timelock path (staking time expired). | |
| 79 | + /// In other words, create a Withdraw transaction. | |
| 80 | + public struct StakingTimelockPath { | |
| 81 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 82 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 83 | + // methods supported on all messages. | |
| 84 | + | |
| 85 | + public var params: TW_BabylonStaking_Proto_StakingInfo { | |
| 86 | + get {return _params ?? TW_BabylonStaking_Proto_StakingInfo()} | |
| 87 | + set {_params = newValue} | |
| 88 | + } | |
| 89 | + /// Returns true if `params` has been explicitly set. | |
| 90 | + public var hasParams: Bool {return self._params != nil} | |
| 91 | + /// Clears the value of `params`. Subsequent reads from it will return its default value. | |
| 92 | + public mutating func clearParams() {self._params = nil} | |
| 93 | + | |
| 94 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 95 | + | |
| 96 | + public init() {} | |
| 97 | + | |
| 98 | + fileprivate var _params: TW_BabylonStaking_Proto_StakingInfo? = nil | |
| 99 | + } | |
| 100 | + | |
| 101 | + /// Spend a Staking Output via unbonding path. | |
| 102 | + /// In other words, create an Unbonding transaction. | |
| 103 | + public struct StakingUnbondingPath { | |
| 104 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 105 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 106 | + // methods supported on all messages. | |
| 107 | + | |
| 108 | + public var params: TW_BabylonStaking_Proto_StakingInfo { | |
| 109 | + get {return _params ?? TW_BabylonStaking_Proto_StakingInfo()} | |
| 110 | + set {_params = newValue} | |
| 111 | + } | |
| 112 | + /// Returns true if `params` has been explicitly set. | |
| 113 | + public var hasParams: Bool {return self._params != nil} | |
| 114 | + /// Clears the value of `params`. Subsequent reads from it will return its default value. | |
| 115 | + public mutating func clearParams() {self._params = nil} | |
| 116 | + | |
| 117 | + /// Signatures signed by covenant committees. | |
| 118 | + /// There can be less signatures than covenant public keys, but not less than `covenant_quorum`. | |
| 119 | + public var covenantCommitteeSignatures: [TW_BabylonStaking_Proto_PublicKeySignature] = [] | |
| 120 | + | |
| 121 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 122 | + | |
| 123 | + public init() {} | |
| 124 | + | |
| 125 | + fileprivate var _params: TW_BabylonStaking_Proto_StakingInfo? = nil | |
| 126 | + } | |
| 127 | + | |
| 128 | + /// Spend a Staking Output via slashing path. | |
| 129 | + /// Slashing path is only used in [ExpressOfInterest](https://github.com/babylonlabs-io/babylon-proto-ts/blob/ef42d04959b326849fe8c9773ab23802573ad407/src/generated/babylon/btcstaking/v1/tx.ts#L61). | |
| 130 | + /// In other words, generate an unsigned Slashing transaction, pre-sign the staker's signature only and share to Babylon PoS chain. | |
| 131 | + public struct StakingSlashingPath { | |
| 132 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 133 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 134 | + // methods supported on all messages. | |
| 135 | + | |
| 136 | + public var params: TW_BabylonStaking_Proto_StakingInfo { | |
| 137 | + get {return _params ?? TW_BabylonStaking_Proto_StakingInfo()} | |
| 138 | + set {_params = newValue} | |
| 139 | + } | |
| 140 | + /// Returns true if `params` has been explicitly set. | |
| 141 | + public var hasParams: Bool {return self._params != nil} | |
| 142 | + /// Clears the value of `params`. Subsequent reads from it will return its default value. | |
| 143 | + public mutating func clearParams() {self._params = nil} | |
| 144 | + | |
| 145 | + /// Empty in most of the cases. Staker's signature can be calculated without the fp signature. | |
| 146 | + public var finalityProviderSignature: TW_BabylonStaking_Proto_PublicKeySignature { | |
| 147 | + get {return _finalityProviderSignature ?? TW_BabylonStaking_Proto_PublicKeySignature()} | |
| 148 | + set {_finalityProviderSignature = newValue} | |
| 149 | + } | |
| 150 | + /// Returns true if `finalityProviderSignature` has been explicitly set. | |
| 151 | + public var hasFinalityProviderSignature: Bool {return self._finalityProviderSignature != nil} | |
| 152 | + /// Clears the value of `finalityProviderSignature`. Subsequent reads from it will return its default value. | |
| 153 | + public mutating func clearFinalityProviderSignature() {self._finalityProviderSignature = nil} | |
| 154 | + | |
| 155 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 156 | + | |
| 157 | + public init() {} | |
| 158 | + | |
| 159 | + fileprivate var _params: TW_BabylonStaking_Proto_StakingInfo? = nil | |
| 160 | + fileprivate var _finalityProviderSignature: TW_BabylonStaking_Proto_PublicKeySignature? = nil | |
| 161 | + } | |
| 162 | + | |
| 163 | + /// Spend an Unbonding Output via timelock path (unbonding time expired). | |
| 164 | + /// In other words, create a Withdraw transaction spending an Unbonding transaction. | |
| 165 | + public struct UnbondingTimelockPath { | |
| 166 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 167 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 168 | + // methods supported on all messages. | |
| 169 | + | |
| 170 | + public var params: TW_BabylonStaking_Proto_StakingInfo { | |
| 171 | + get {return _params ?? TW_BabylonStaking_Proto_StakingInfo()} | |
| 172 | + set {_params = newValue} | |
| 173 | + } | |
| 174 | + /// Returns true if `params` has been explicitly set. | |
| 175 | + public var hasParams: Bool {return self._params != nil} | |
| 176 | + /// Clears the value of `params`. Subsequent reads from it will return its default value. | |
| 177 | + public mutating func clearParams() {self._params = nil} | |
| 178 | + | |
| 179 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 180 | + | |
| 181 | + public init() {} | |
| 182 | + | |
| 183 | + fileprivate var _params: TW_BabylonStaking_Proto_StakingInfo? = nil | |
| 184 | + } | |
| 185 | + | |
| 186 | + /// Spend an Unbonding Output via slashing path. | |
| 187 | + /// Slashing path is only used in [ExpressOfInterest](https://github.com/babylonlabs-io/babylon-proto-ts/blob/ef42d04959b326849fe8c9773ab23802573ad407/src/generated/babylon/btcstaking/v1/tx.ts#L61). | |
| 188 | + /// In other words, generate an unsigned Slashing transaction, pre-sign the staker's signature only and share to Babylon PoS chain. | |
| 189 | + public struct UnbondingSlashingPath { | |
| 190 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 191 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 192 | + // methods supported on all messages. | |
| 193 | + | |
| 194 | + public var params: TW_BabylonStaking_Proto_StakingInfo { | |
| 195 | + get {return _params ?? TW_BabylonStaking_Proto_StakingInfo()} | |
| 196 | + set {_params = newValue} | |
| 197 | + } | |
| 198 | + /// Returns true if `params` has been explicitly set. | |
| 199 | + public var hasParams: Bool {return self._params != nil} | |
| 200 | + /// Clears the value of `params`. Subsequent reads from it will return its default value. | |
| 201 | + public mutating func clearParams() {self._params = nil} | |
| 202 | + | |
| 203 | + /// Empty in most of the cases. Staker's signature can be calculated without the fp signature. | |
| 204 | + public var finalityProviderSignature: TW_BabylonStaking_Proto_PublicKeySignature { | |
| 205 | + get {return _finalityProviderSignature ?? TW_BabylonStaking_Proto_PublicKeySignature()} | |
| 206 | + set {_finalityProviderSignature = newValue} | |
| 207 | + } | |
| 208 | + /// Returns true if `finalityProviderSignature` has been explicitly set. | |
| 209 | + public var hasFinalityProviderSignature: Bool {return self._finalityProviderSignature != nil} | |
| 210 | + /// Clears the value of `finalityProviderSignature`. Subsequent reads from it will return its default value. | |
| 211 | + public mutating func clearFinalityProviderSignature() {self._finalityProviderSignature = nil} | |
| 212 | + | |
| 213 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 214 | + | |
| 215 | + public init() {} | |
| 216 | + | |
| 217 | + fileprivate var _params: TW_BabylonStaking_Proto_StakingInfo? = nil | |
| 218 | + fileprivate var _finalityProviderSignature: TW_BabylonStaking_Proto_PublicKeySignature? = nil | |
| 219 | + } | |
| 220 | + | |
| 221 | + public init() {} | |
| 222 | +} | |
| 223 | + | |
| 224 | +public struct TW_BabylonStaking_Proto_OutputBuilder { | |
| 225 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 226 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 227 | + // methods supported on all messages. | |
| 228 | + | |
| 229 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 230 | + | |
| 231 | + /// Create a Staking Output. | |
| 232 | + public struct StakingOutput { | |
| 233 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 234 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 235 | + // methods supported on all messages. | |
| 236 | + | |
| 237 | + public var params: TW_BabylonStaking_Proto_StakingInfo { | |
| 238 | + get {return _params ?? TW_BabylonStaking_Proto_StakingInfo()} | |
| 239 | + set {_params = newValue} | |
| 240 | + } | |
| 241 | + /// Returns true if `params` has been explicitly set. | |
| 242 | + public var hasParams: Bool {return self._params != nil} | |
| 243 | + /// Clears the value of `params`. Subsequent reads from it will return its default value. | |
| 244 | + public mutating func clearParams() {self._params = nil} | |
| 245 | + | |
| 246 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 247 | + | |
| 248 | + public init() {} | |
| 249 | + | |
| 250 | + fileprivate var _params: TW_BabylonStaking_Proto_StakingInfo? = nil | |
| 251 | + } | |
| 252 | + | |
| 253 | + /// Create an Unbonding Output. | |
| 254 | + public struct UnbondingOutput { | |
| 255 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 256 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 257 | + // methods supported on all messages. | |
| 258 | + | |
| 259 | + public var params: TW_BabylonStaking_Proto_StakingInfo { | |
| 260 | + get {return _params ?? TW_BabylonStaking_Proto_StakingInfo()} | |
| 261 | + set {_params = newValue} | |
| 262 | + } | |
| 263 | + /// Returns true if `params` has been explicitly set. | |
| 264 | + public var hasParams: Bool {return self._params != nil} | |
| 265 | + /// Clears the value of `params`. Subsequent reads from it will return its default value. | |
| 266 | + public mutating func clearParams() {self._params = nil} | |
| 267 | + | |
| 268 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 269 | + | |
| 270 | + public init() {} | |
| 271 | + | |
| 272 | + fileprivate var _params: TW_BabylonStaking_Proto_StakingInfo? = nil | |
| 273 | + } | |
| 274 | + | |
| 275 | + /// Creates an OP_RETURN output used to identify the staking transaction among other transactions in the Bitcoin ledger. | |
| 276 | + public struct OpReturn { | |
| 277 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 278 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 279 | + // methods supported on all messages. | |
| 280 | + | |
| 281 | + /// Retrieved from global_parameters.Tag. | |
| 282 | + public var tag: Data = Data() | |
| 283 | + | |
| 284 | + /// User's public key. | |
| 285 | + public var stakerPublicKey: Data = Data() | |
| 286 | + | |
| 287 | + /// Finality provider's public key chosen by the user. | |
| 288 | + public var finalityProviderPublicKey: Data = Data() | |
| 289 | + | |
| 290 | + /// global_parameters.min_staking_time <= staking_time <= global_parameters.max_staking_time. | |
| 291 | + public var stakingTime: UInt32 = 0 | |
| 292 | + | |
| 293 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 294 | + | |
| 295 | + public init() {} | |
| 296 | + } | |
| 297 | + | |
| 298 | + public init() {} | |
| 299 | +} | |
| 300 | + | |
| 301 | +// MARK: - Code below here is support for the SwiftProtobuf.runtime. | |
| 302 | + | |
| 303 | +fileprivate let _protobuf_package = "TW.BabylonStaking.Proto" | |
| 304 | + | |
| 305 | +extension TW_BabylonStaking_Proto_PublicKeySignature: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 306 | + public static let protoMessageName: String = _protobuf_package + ".PublicKeySignature" | |
| 307 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 308 | + 1: .standard(proto: "public_key"), | |
| 309 | + 2: .same(proto: "signature"), | |
| 310 | + ] | |
| 311 | + | |
| 312 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 313 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 314 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 315 | + // allocates stack space for every case branch when no optimizations are | |
| 316 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 317 | + switch fieldNumber { | |
| 318 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.publicKey) }() | |
| 319 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.signature) }() | |
| 320 | + default: break | |
| 321 | + } | |
| 322 | + } | |
| 323 | + } | |
| 324 | + | |
| 325 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 326 | + if !self.publicKey.isEmpty { | |
| 327 | + try visitor.visitSingularBytesField(value: self.publicKey, fieldNumber: 1) | |
| 328 | + } | |
| 329 | + if !self.signature.isEmpty { | |
| 330 | + try visitor.visitSingularBytesField(value: self.signature, fieldNumber: 2) | |
| 331 | + } | |
| 332 | + try unknownFields.traverse(visitor: &visitor) | |
| 333 | + } | |
| 334 | + | |
| 335 | + public static func ==(lhs: TW_BabylonStaking_Proto_PublicKeySignature, rhs: TW_BabylonStaking_Proto_PublicKeySignature) -> Bool { | |
| 336 | + if lhs.publicKey != rhs.publicKey {return false} | |
| 337 | + if lhs.signature != rhs.signature {return false} | |
| 338 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 339 | + return true | |
| 340 | + } | |
| 341 | +} | |
| 342 | + | |
| 343 | +extension TW_BabylonStaking_Proto_StakingInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 344 | + public static let protoMessageName: String = _protobuf_package + ".StakingInfo" | |
| 345 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 346 | + 1: .standard(proto: "staker_public_key"), | |
| 347 | + 2: .standard(proto: "finality_provider_public_key"), | |
| 348 | + 3: .standard(proto: "staking_time"), | |
| 349 | + 4: .standard(proto: "covenant_committee_public_keys"), | |
| 350 | + 5: .standard(proto: "covenant_quorum"), | |
| 351 | + ] | |
| 352 | + | |
| 353 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 354 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 355 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 356 | + // allocates stack space for every case branch when no optimizations are | |
| 357 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 358 | + switch fieldNumber { | |
| 359 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.stakerPublicKey) }() | |
| 360 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.finalityProviderPublicKey) }() | |
| 361 | + case 3: try { try decoder.decodeSingularUInt32Field(value: &self.stakingTime) }() | |
| 362 | + case 4: try { try decoder.decodeRepeatedBytesField(value: &self.covenantCommitteePublicKeys) }() | |
| 363 | + case 5: try { try decoder.decodeSingularUInt32Field(value: &self.covenantQuorum) }() | |
| 364 | + default: break | |
| 365 | + } | |
| 366 | + } | |
| 367 | + } | |
| 368 | + | |
| 369 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 370 | + if !self.stakerPublicKey.isEmpty { | |
| 371 | + try visitor.visitSingularBytesField(value: self.stakerPublicKey, fieldNumber: 1) | |
| 372 | + } | |
| 373 | + if !self.finalityProviderPublicKey.isEmpty { | |
| 374 | + try visitor.visitSingularBytesField(value: self.finalityProviderPublicKey, fieldNumber: 2) | |
| 375 | + } | |
| 376 | + if self.stakingTime != 0 { | |
| 377 | + try visitor.visitSingularUInt32Field(value: self.stakingTime, fieldNumber: 3) | |
| 378 | + } | |
| 379 | + if !self.covenantCommitteePublicKeys.isEmpty { | |
| 380 | + try visitor.visitRepeatedBytesField(value: self.covenantCommitteePublicKeys, fieldNumber: 4) | |
| 381 | + } | |
| 382 | + if self.covenantQuorum != 0 { | |
| 383 | + try visitor.visitSingularUInt32Field(value: self.covenantQuorum, fieldNumber: 5) | |
| 384 | + } | |
| 385 | + try unknownFields.traverse(visitor: &visitor) | |
| 386 | + } | |
| 387 | + | |
| 388 | + public static func ==(lhs: TW_BabylonStaking_Proto_StakingInfo, rhs: TW_BabylonStaking_Proto_StakingInfo) -> Bool { | |
| 389 | + if lhs.stakerPublicKey != rhs.stakerPublicKey {return false} | |
| 390 | + if lhs.finalityProviderPublicKey != rhs.finalityProviderPublicKey {return false} | |
| 391 | + if lhs.stakingTime != rhs.stakingTime {return false} | |
| 392 | + if lhs.covenantCommitteePublicKeys != rhs.covenantCommitteePublicKeys {return false} | |
| 393 | + if lhs.covenantQuorum != rhs.covenantQuorum {return false} | |
| 394 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 395 | + return true | |
| 396 | + } | |
| 397 | +} | |
| 398 | + | |
| 399 | +extension TW_BabylonStaking_Proto_InputBuilder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 400 | + public static let protoMessageName: String = _protobuf_package + ".InputBuilder" | |
| 401 | + public static let _protobuf_nameMap = SwiftProtobuf._NameMap() | |
| 402 | + | |
| 403 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 404 | + while let _ = try decoder.nextFieldNumber() { | |
| 405 | + } | |
| 406 | + } | |
| 407 | + | |
| 408 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 409 | + try unknownFields.traverse(visitor: &visitor) | |
| 410 | + } | |
| 411 | + | |
| 412 | + public static func ==(lhs: TW_BabylonStaking_Proto_InputBuilder, rhs: TW_BabylonStaking_Proto_InputBuilder) -> Bool { | |
| 413 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 414 | + return true | |
| 415 | + } | |
| 416 | +} | |
| 417 | + | |
| 418 | +extension TW_BabylonStaking_Proto_InputBuilder.StakingTimelockPath: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 419 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_InputBuilder.protoMessageName + ".StakingTimelockPath" | |
| 420 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 421 | + 1: .same(proto: "params"), | |
| 422 | + ] | |
| 423 | + | |
| 424 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 425 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 426 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 427 | + // allocates stack space for every case branch when no optimizations are | |
| 428 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 429 | + switch fieldNumber { | |
| 430 | + case 1: try { try decoder.decodeSingularMessageField(value: &self._params) }() | |
| 431 | + default: break | |
| 432 | + } | |
| 433 | + } | |
| 434 | + } | |
| 435 | + | |
| 436 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 437 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 438 | + // allocates stack space for every if/case branch local when no optimizations | |
| 439 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 440 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 441 | + try { if let v = self._params { | |
| 442 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 443 | + } }() | |
| 444 | + try unknownFields.traverse(visitor: &visitor) | |
| 445 | + } | |
| 446 | + | |
| 447 | + public static func ==(lhs: TW_BabylonStaking_Proto_InputBuilder.StakingTimelockPath, rhs: TW_BabylonStaking_Proto_InputBuilder.StakingTimelockPath) -> Bool { | |
| 448 | + if lhs._params != rhs._params {return false} | |
| 449 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 450 | + return true | |
| 451 | + } | |
| 452 | +} | |
| 453 | + | |
| 454 | +extension TW_BabylonStaking_Proto_InputBuilder.StakingUnbondingPath: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 455 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_InputBuilder.protoMessageName + ".StakingUnbondingPath" | |
| 456 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 457 | + 1: .same(proto: "params"), | |
| 458 | + 2: .standard(proto: "covenant_committee_signatures"), | |
| 459 | + ] | |
| 460 | + | |
| 461 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 462 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 463 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 464 | + // allocates stack space for every case branch when no optimizations are | |
| 465 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 466 | + switch fieldNumber { | |
| 467 | + case 1: try { try decoder.decodeSingularMessageField(value: &self._params) }() | |
| 468 | + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.covenantCommitteeSignatures) }() | |
| 469 | + default: break | |
| 470 | + } | |
| 471 | + } | |
| 472 | + } | |
| 473 | + | |
| 474 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 475 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 476 | + // allocates stack space for every if/case branch local when no optimizations | |
| 477 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 478 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 479 | + try { if let v = self._params { | |
| 480 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 481 | + } }() | |
| 482 | + if !self.covenantCommitteeSignatures.isEmpty { | |
| 483 | + try visitor.visitRepeatedMessageField(value: self.covenantCommitteeSignatures, fieldNumber: 2) | |
| 484 | + } | |
| 485 | + try unknownFields.traverse(visitor: &visitor) | |
| 486 | + } | |
| 487 | + | |
| 488 | + public static func ==(lhs: TW_BabylonStaking_Proto_InputBuilder.StakingUnbondingPath, rhs: TW_BabylonStaking_Proto_InputBuilder.StakingUnbondingPath) -> Bool { | |
| 489 | + if lhs._params != rhs._params {return false} | |
| 490 | + if lhs.covenantCommitteeSignatures != rhs.covenantCommitteeSignatures {return false} | |
| 491 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 492 | + return true | |
| 493 | + } | |
| 494 | +} | |
| 495 | + | |
| 496 | +extension TW_BabylonStaking_Proto_InputBuilder.StakingSlashingPath: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 497 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_InputBuilder.protoMessageName + ".StakingSlashingPath" | |
| 498 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 499 | + 1: .same(proto: "params"), | |
| 500 | + 2: .standard(proto: "finality_provider_signature"), | |
| 501 | + ] | |
| 502 | + | |
| 503 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 504 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 505 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 506 | + // allocates stack space for every case branch when no optimizations are | |
| 507 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 508 | + switch fieldNumber { | |
| 509 | + case 1: try { try decoder.decodeSingularMessageField(value: &self._params) }() | |
| 510 | + case 2: try { try decoder.decodeSingularMessageField(value: &self._finalityProviderSignature) }() | |
| 511 | + default: break | |
| 512 | + } | |
| 513 | + } | |
| 514 | + } | |
| 515 | + | |
| 516 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 517 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 518 | + // allocates stack space for every if/case branch local when no optimizations | |
| 519 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 520 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 521 | + try { if let v = self._params { | |
| 522 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 523 | + } }() | |
| 524 | + try { if let v = self._finalityProviderSignature { | |
| 525 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) | |
| 526 | + } }() | |
| 527 | + try unknownFields.traverse(visitor: &visitor) | |
| 528 | + } | |
| 529 | + | |
| 530 | + public static func ==(lhs: TW_BabylonStaking_Proto_InputBuilder.StakingSlashingPath, rhs: TW_BabylonStaking_Proto_InputBuilder.StakingSlashingPath) -> Bool { | |
| 531 | + if lhs._params != rhs._params {return false} | |
| 532 | + if lhs._finalityProviderSignature != rhs._finalityProviderSignature {return false} | |
| 533 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 534 | + return true | |
| 535 | + } | |
| 536 | +} | |
| 537 | + | |
| 538 | +extension TW_BabylonStaking_Proto_InputBuilder.UnbondingTimelockPath: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 539 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_InputBuilder.protoMessageName + ".UnbondingTimelockPath" | |
| 540 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 541 | + 1: .same(proto: "params"), | |
| 542 | + ] | |
| 543 | + | |
| 544 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 545 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 546 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 547 | + // allocates stack space for every case branch when no optimizations are | |
| 548 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 549 | + switch fieldNumber { | |
| 550 | + case 1: try { try decoder.decodeSingularMessageField(value: &self._params) }() | |
| 551 | + default: break | |
| 552 | + } | |
| 553 | + } | |
| 554 | + } | |
| 555 | + | |
| 556 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 557 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 558 | + // allocates stack space for every if/case branch local when no optimizations | |
| 559 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 560 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 561 | + try { if let v = self._params { | |
| 562 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 563 | + } }() | |
| 564 | + try unknownFields.traverse(visitor: &visitor) | |
| 565 | + } | |
| 566 | + | |
| 567 | + public static func ==(lhs: TW_BabylonStaking_Proto_InputBuilder.UnbondingTimelockPath, rhs: TW_BabylonStaking_Proto_InputBuilder.UnbondingTimelockPath) -> Bool { | |
| 568 | + if lhs._params != rhs._params {return false} | |
| 569 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 570 | + return true | |
| 571 | + } | |
| 572 | +} | |
| 573 | + | |
| 574 | +extension TW_BabylonStaking_Proto_InputBuilder.UnbondingSlashingPath: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 575 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_InputBuilder.protoMessageName + ".UnbondingSlashingPath" | |
| 576 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 577 | + 1: .same(proto: "params"), | |
| 578 | + 2: .standard(proto: "finality_provider_signature"), | |
| 579 | + ] | |
| 580 | + | |
| 581 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 582 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 583 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 584 | + // allocates stack space for every case branch when no optimizations are | |
| 585 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 586 | + switch fieldNumber { | |
| 587 | + case 1: try { try decoder.decodeSingularMessageField(value: &self._params) }() | |
| 588 | + case 2: try { try decoder.decodeSingularMessageField(value: &self._finalityProviderSignature) }() | |
| 589 | + default: break | |
| 590 | + } | |
| 591 | + } | |
| 592 | + } | |
| 593 | + | |
| 594 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 595 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 596 | + // allocates stack space for every if/case branch local when no optimizations | |
| 597 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 598 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 599 | + try { if let v = self._params { | |
| 600 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 601 | + } }() | |
| 602 | + try { if let v = self._finalityProviderSignature { | |
| 603 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 2) | |
| 604 | + } }() | |
| 605 | + try unknownFields.traverse(visitor: &visitor) | |
| 606 | + } | |
| 607 | + | |
| 608 | + public static func ==(lhs: TW_BabylonStaking_Proto_InputBuilder.UnbondingSlashingPath, rhs: TW_BabylonStaking_Proto_InputBuilder.UnbondingSlashingPath) -> Bool { | |
| 609 | + if lhs._params != rhs._params {return false} | |
| 610 | + if lhs._finalityProviderSignature != rhs._finalityProviderSignature {return false} | |
| 611 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 612 | + return true | |
| 613 | + } | |
| 614 | +} | |
| 615 | + | |
| 616 | +extension TW_BabylonStaking_Proto_OutputBuilder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 617 | + public static let protoMessageName: String = _protobuf_package + ".OutputBuilder" | |
| 618 | + public static let _protobuf_nameMap = SwiftProtobuf._NameMap() | |
| 619 | + | |
| 620 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 621 | + while let _ = try decoder.nextFieldNumber() { | |
| 622 | + } | |
| 623 | + } | |
| 624 | + | |
| 625 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 626 | + try unknownFields.traverse(visitor: &visitor) | |
| 627 | + } | |
| 628 | + | |
| 629 | + public static func ==(lhs: TW_BabylonStaking_Proto_OutputBuilder, rhs: TW_BabylonStaking_Proto_OutputBuilder) -> Bool { | |
| 630 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 631 | + return true | |
| 632 | + } | |
| 633 | +} | |
| 634 | + | |
| 635 | +extension TW_BabylonStaking_Proto_OutputBuilder.StakingOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 636 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_OutputBuilder.protoMessageName + ".StakingOutput" | |
| 637 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 638 | + 1: .same(proto: "params"), | |
| 639 | + ] | |
| 640 | + | |
| 641 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 642 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 643 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 644 | + // allocates stack space for every case branch when no optimizations are | |
| 645 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 646 | + switch fieldNumber { | |
| 647 | + case 1: try { try decoder.decodeSingularMessageField(value: &self._params) }() | |
| 648 | + default: break | |
| 649 | + } | |
| 650 | + } | |
| 651 | + } | |
| 652 | + | |
| 653 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 654 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 655 | + // allocates stack space for every if/case branch local when no optimizations | |
| 656 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 657 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 658 | + try { if let v = self._params { | |
| 659 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 660 | + } }() | |
| 661 | + try unknownFields.traverse(visitor: &visitor) | |
| 662 | + } | |
| 663 | + | |
| 664 | + public static func ==(lhs: TW_BabylonStaking_Proto_OutputBuilder.StakingOutput, rhs: TW_BabylonStaking_Proto_OutputBuilder.StakingOutput) -> Bool { | |
| 665 | + if lhs._params != rhs._params {return false} | |
| 666 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 667 | + return true | |
| 668 | + } | |
| 669 | +} | |
| 670 | + | |
| 671 | +extension TW_BabylonStaking_Proto_OutputBuilder.UnbondingOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 672 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_OutputBuilder.protoMessageName + ".UnbondingOutput" | |
| 673 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 674 | + 1: .same(proto: "params"), | |
| 675 | + ] | |
| 676 | + | |
| 677 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 678 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 679 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 680 | + // allocates stack space for every case branch when no optimizations are | |
| 681 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 682 | + switch fieldNumber { | |
| 683 | + case 1: try { try decoder.decodeSingularMessageField(value: &self._params) }() | |
| 684 | + default: break | |
| 685 | + } | |
| 686 | + } | |
| 687 | + } | |
| 688 | + | |
| 689 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 690 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 691 | + // allocates stack space for every if/case branch local when no optimizations | |
| 692 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 693 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 694 | + try { if let v = self._params { | |
| 695 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 1) | |
| 696 | + } }() | |
| 697 | + try unknownFields.traverse(visitor: &visitor) | |
| 698 | + } | |
| 699 | + | |
| 700 | + public static func ==(lhs: TW_BabylonStaking_Proto_OutputBuilder.UnbondingOutput, rhs: TW_BabylonStaking_Proto_OutputBuilder.UnbondingOutput) -> Bool { | |
| 701 | + if lhs._params != rhs._params {return false} | |
| 702 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 703 | + return true | |
| 704 | + } | |
| 705 | +} | |
| 706 | + | |
| 707 | +extension TW_BabylonStaking_Proto_OutputBuilder.OpReturn: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 708 | + public static let protoMessageName: String = TW_BabylonStaking_Proto_OutputBuilder.protoMessageName + ".OpReturn" | |
| 709 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 710 | + 1: .same(proto: "tag"), | |
| 711 | + 2: .standard(proto: "staker_public_key"), | |
| 712 | + 3: .standard(proto: "finality_provider_public_key"), | |
| 713 | + 4: .standard(proto: "staking_time"), | |
| 714 | + ] | |
| 715 | + | |
| 716 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 717 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 718 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 719 | + // allocates stack space for every case branch when no optimizations are | |
| 720 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 721 | + switch fieldNumber { | |
| 722 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.tag) }() | |
| 723 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.stakerPublicKey) }() | |
| 724 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.finalityProviderPublicKey) }() | |
| 725 | + case 4: try { try decoder.decodeSingularUInt32Field(value: &self.stakingTime) }() | |
| 726 | + default: break | |
| 727 | + } | |
| 728 | + } | |
| 729 | + } | |
| 730 | + | |
| 731 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 732 | + if !self.tag.isEmpty { | |
| 733 | + try visitor.visitSingularBytesField(value: self.tag, fieldNumber: 1) | |
| 734 | + } | |
| 735 | + if !self.stakerPublicKey.isEmpty { | |
| 736 | + try visitor.visitSingularBytesField(value: self.stakerPublicKey, fieldNumber: 2) | |
| 737 | + } | |
| 738 | + if !self.finalityProviderPublicKey.isEmpty { | |
| 739 | + try visitor.visitSingularBytesField(value: self.finalityProviderPublicKey, fieldNumber: 3) | |
| 740 | + } | |
| 741 | + if self.stakingTime != 0 { | |
| 742 | + try visitor.visitSingularUInt32Field(value: self.stakingTime, fieldNumber: 4) | |
| 743 | + } | |
| 744 | + try unknownFields.traverse(visitor: &visitor) | |
| 745 | + } | |
| 746 | + | |
| 747 | + public static func ==(lhs: TW_BabylonStaking_Proto_OutputBuilder.OpReturn, rhs: TW_BabylonStaking_Proto_OutputBuilder.OpReturn) -> Bool { | |
| 748 | + if lhs.tag != rhs.tag {return false} | |
| 749 | + if lhs.stakerPublicKey != rhs.stakerPublicKey {return false} | |
| 750 | + if lhs.finalityProviderPublicKey != rhs.finalityProviderPublicKey {return false} | |
| 751 | + if lhs.stakingTime != rhs.stakingTime {return false} | |
| 752 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 753 | + return true | |
| 754 | + } | |
| 755 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Barz+Proto.swift
+10 −0
@@ -0,0 +1,10 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public typealias BarzContractAddressInput = TW_Barz_Proto_ContractAddressInput | |
| 8 | +public typealias BarzFacetCut = TW_Barz_Proto_FacetCut | |
| 9 | +public typealias BarzDiamondCutInput = TW_Barz_Proto_DiamondCutInput | |
| 10 | +public typealias BarzFacetCutAction = TW_Barz_Proto_FacetCutAction | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Barz.pb.swift
+327 −0
@@ -0,0 +1,327 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// DO NOT EDIT. | |
| 4 | +// swift-format-ignore-file | |
| 5 | +// | |
| 6 | +// Generated by the Swift generator plugin for the protocol buffer compiler. | |
| 7 | +// Source: Barz.proto | |
| 8 | +// | |
| 9 | +// For information on using the generated types, please see the documentation: | |
| 10 | +// https://github.com/apple/swift-protobuf/ | |
| 11 | + | |
| 12 | +// SPDX-License-Identifier: Apache-2.0 | |
| 13 | +// | |
| 14 | +// Copyright © 2017 Trust Wallet. | |
| 15 | + | |
| 16 | +import Foundation | |
| 17 | +import SwiftProtobuf | |
| 18 | + | |
| 19 | +// If the compiler emits an error on this type, it is because this file | |
| 20 | +// was generated by a version of the `protoc` Swift plug-in that is | |
| 21 | +// incompatible with the version of SwiftProtobuf.to which you are linking. | |
| 22 | +// Please ensure that you are building against the same version of the API | |
| 23 | +// that was used to generate this file. | |
| 24 | +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { | |
| 25 | + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} | |
| 26 | + typealias Version = _2 | |
| 27 | +} | |
| 28 | + | |
| 29 | +/// FacetCutAction represents the action to be performed for a FacetCut | |
| 30 | +public enum TW_Barz_Proto_FacetCutAction: SwiftProtobuf.Enum { | |
| 31 | + public typealias RawValue = Int | |
| 32 | + case add // = 0 | |
| 33 | + case replace // = 1 | |
| 34 | + case remove // = 2 | |
| 35 | + case UNRECOGNIZED(Int) | |
| 36 | + | |
| 37 | + public init() { | |
| 38 | + self = .add | |
| 39 | + } | |
| 40 | + | |
| 41 | + public init?(rawValue: Int) { | |
| 42 | + switch rawValue { | |
| 43 | + case 0: self = .add | |
| 44 | + case 1: self = .replace | |
| 45 | + case 2: self = .remove | |
| 46 | + default: self = .UNRECOGNIZED(rawValue) | |
| 47 | + } | |
| 48 | + } | |
| 49 | + | |
| 50 | + public var rawValue: Int { | |
| 51 | + switch self { | |
| 52 | + case .add: return 0 | |
| 53 | + case .replace: return 1 | |
| 54 | + case .remove: return 2 | |
| 55 | + case .UNRECOGNIZED(let i): return i | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | +} | |
| 60 | + | |
| 61 | +#if swift(>=4.2) | |
| 62 | + | |
| 63 | +extension TW_Barz_Proto_FacetCutAction: CaseIterable { | |
| 64 | + // The compiler won't synthesize support with the UNRECOGNIZED case. | |
| 65 | + public static var allCases: [TW_Barz_Proto_FacetCutAction] = [ | |
| 66 | + .add, | |
| 67 | + .replace, | |
| 68 | + .remove, | |
| 69 | + ] | |
| 70 | +} | |
| 71 | + | |
| 72 | +#endif // swift(>=4.2) | |
| 73 | + | |
| 74 | +/// Input parameters for calculating a counterfactual address for ERC-4337 based smart contract wallet | |
| 75 | +public struct TW_Barz_Proto_ContractAddressInput { | |
| 76 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 77 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 78 | + // methods supported on all messages. | |
| 79 | + | |
| 80 | + /// ERC-4337 entry point | |
| 81 | + public var entryPoint: String = String() | |
| 82 | + | |
| 83 | + /// Address of the contract factory | |
| 84 | + public var factory: String = String() | |
| 85 | + | |
| 86 | + /// Diamond proxy facets required for the contract setup | |
| 87 | + public var accountFacet: String = String() | |
| 88 | + | |
| 89 | + public var verificationFacet: String = String() | |
| 90 | + | |
| 91 | + public var facetRegistry: String = String() | |
| 92 | + | |
| 93 | + public var defaultFallback: String = String() | |
| 94 | + | |
| 95 | + /// Bytecode of the smart contract to deploy | |
| 96 | + public var bytecode: String = String() | |
| 97 | + | |
| 98 | + /// PublicKey of the wallet | |
| 99 | + public var publicKey: String = String() | |
| 100 | + | |
| 101 | + /// Salt is used to derive multiple account from the same public key | |
| 102 | + public var salt: UInt32 = 0 | |
| 103 | + | |
| 104 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 105 | + | |
| 106 | + public init() {} | |
| 107 | +} | |
| 108 | + | |
| 109 | +/// FacetCut represents a single operation to be performed on a facet | |
| 110 | +public struct TW_Barz_Proto_FacetCut { | |
| 111 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 112 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 113 | + // methods supported on all messages. | |
| 114 | + | |
| 115 | + /// The address of the facet | |
| 116 | + public var facetAddress: String = String() | |
| 117 | + | |
| 118 | + /// The action to perform | |
| 119 | + public var action: TW_Barz_Proto_FacetCutAction = .add | |
| 120 | + | |
| 121 | + /// List of function selectors, each is bytes4 | |
| 122 | + public var functionSelectors: [Data] = [] | |
| 123 | + | |
| 124 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 125 | + | |
| 126 | + public init() {} | |
| 127 | +} | |
| 128 | + | |
| 129 | +/// DiamondCutInput represents the input parameters for a diamondCut operation | |
| 130 | +public struct TW_Barz_Proto_DiamondCutInput { | |
| 131 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 132 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 133 | + // methods supported on all messages. | |
| 134 | + | |
| 135 | + /// List of facet cuts to apply | |
| 136 | + public var facetCuts: [TW_Barz_Proto_FacetCut] = [] | |
| 137 | + | |
| 138 | + /// Address to call with `init` data after applying cuts | |
| 139 | + public var initAddress: String = String() | |
| 140 | + | |
| 141 | + /// Data to pass to `init` function call | |
| 142 | + public var initData: Data = Data() | |
| 143 | + | |
| 144 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 145 | + | |
| 146 | + public init() {} | |
| 147 | +} | |
| 148 | + | |
| 149 | +// MARK: - Code below here is support for the SwiftProtobuf.runtime. | |
| 150 | + | |
| 151 | +fileprivate let _protobuf_package = "TW.Barz.Proto" | |
| 152 | + | |
| 153 | +extension TW_Barz_Proto_FacetCutAction: SwiftProtobuf._ProtoNameProviding { | |
| 154 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 155 | + 0: .same(proto: "ADD"), | |
| 156 | + 1: .same(proto: "REPLACE"), | |
| 157 | + 2: .same(proto: "REMOVE"), | |
| 158 | + ] | |
| 159 | +} | |
| 160 | + | |
| 161 | +extension TW_Barz_Proto_ContractAddressInput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 162 | + public static let protoMessageName: String = _protobuf_package + ".ContractAddressInput" | |
| 163 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 164 | + 1: .standard(proto: "entry_point"), | |
| 165 | + 2: .same(proto: "factory"), | |
| 166 | + 3: .standard(proto: "account_facet"), | |
| 167 | + 4: .standard(proto: "verification_facet"), | |
| 168 | + 5: .standard(proto: "facet_registry"), | |
| 169 | + 6: .standard(proto: "default_fallback"), | |
| 170 | + 7: .same(proto: "bytecode"), | |
| 171 | + 8: .standard(proto: "public_key"), | |
| 172 | + 9: .same(proto: "salt"), | |
| 173 | + ] | |
| 174 | + | |
| 175 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 176 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 177 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 178 | + // allocates stack space for every case branch when no optimizations are | |
| 179 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 180 | + switch fieldNumber { | |
| 181 | + case 1: try { try decoder.decodeSingularStringField(value: &self.entryPoint) }() | |
| 182 | + case 2: try { try decoder.decodeSingularStringField(value: &self.factory) }() | |
| 183 | + case 3: try { try decoder.decodeSingularStringField(value: &self.accountFacet) }() | |
| 184 | + case 4: try { try decoder.decodeSingularStringField(value: &self.verificationFacet) }() | |
| 185 | + case 5: try { try decoder.decodeSingularStringField(value: &self.facetRegistry) }() | |
| 186 | + case 6: try { try decoder.decodeSingularStringField(value: &self.defaultFallback) }() | |
| 187 | + case 7: try { try decoder.decodeSingularStringField(value: &self.bytecode) }() | |
| 188 | + case 8: try { try decoder.decodeSingularStringField(value: &self.publicKey) }() | |
| 189 | + case 9: try { try decoder.decodeSingularUInt32Field(value: &self.salt) }() | |
| 190 | + default: break | |
| 191 | + } | |
| 192 | + } | |
| 193 | + } | |
| 194 | + | |
| 195 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 196 | + if !self.entryPoint.isEmpty { | |
| 197 | + try visitor.visitSingularStringField(value: self.entryPoint, fieldNumber: 1) | |
| 198 | + } | |
| 199 | + if !self.factory.isEmpty { | |
| 200 | + try visitor.visitSingularStringField(value: self.factory, fieldNumber: 2) | |
| 201 | + } | |
| 202 | + if !self.accountFacet.isEmpty { | |
| 203 | + try visitor.visitSingularStringField(value: self.accountFacet, fieldNumber: 3) | |
| 204 | + } | |
| 205 | + if !self.verificationFacet.isEmpty { | |
| 206 | + try visitor.visitSingularStringField(value: self.verificationFacet, fieldNumber: 4) | |
| 207 | + } | |
| 208 | + if !self.facetRegistry.isEmpty { | |
| 209 | + try visitor.visitSingularStringField(value: self.facetRegistry, fieldNumber: 5) | |
| 210 | + } | |
| 211 | + if !self.defaultFallback.isEmpty { | |
| 212 | + try visitor.visitSingularStringField(value: self.defaultFallback, fieldNumber: 6) | |
| 213 | + } | |
| 214 | + if !self.bytecode.isEmpty { | |
| 215 | + try visitor.visitSingularStringField(value: self.bytecode, fieldNumber: 7) | |
| 216 | + } | |
| 217 | + if !self.publicKey.isEmpty { | |
| 218 | + try visitor.visitSingularStringField(value: self.publicKey, fieldNumber: 8) | |
| 219 | + } | |
| 220 | + if self.salt != 0 { | |
| 221 | + try visitor.visitSingularUInt32Field(value: self.salt, fieldNumber: 9) | |
| 222 | + } | |
| 223 | + try unknownFields.traverse(visitor: &visitor) | |
| 224 | + } | |
| 225 | + | |
| 226 | + public static func ==(lhs: TW_Barz_Proto_ContractAddressInput, rhs: TW_Barz_Proto_ContractAddressInput) -> Bool { | |
| 227 | + if lhs.entryPoint != rhs.entryPoint {return false} | |
| 228 | + if lhs.factory != rhs.factory {return false} | |
| 229 | + if lhs.accountFacet != rhs.accountFacet {return false} | |
| 230 | + if lhs.verificationFacet != rhs.verificationFacet {return false} | |
| 231 | + if lhs.facetRegistry != rhs.facetRegistry {return false} | |
| 232 | + if lhs.defaultFallback != rhs.defaultFallback {return false} | |
| 233 | + if lhs.bytecode != rhs.bytecode {return false} | |
| 234 | + if lhs.publicKey != rhs.publicKey {return false} | |
| 235 | + if lhs.salt != rhs.salt {return false} | |
| 236 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 237 | + return true | |
| 238 | + } | |
| 239 | +} | |
| 240 | + | |
| 241 | +extension TW_Barz_Proto_FacetCut: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 242 | + public static let protoMessageName: String = _protobuf_package + ".FacetCut" | |
| 243 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 244 | + 1: .standard(proto: "facet_address"), | |
| 245 | + 2: .same(proto: "action"), | |
| 246 | + 3: .standard(proto: "function_selectors"), | |
| 247 | + ] | |
| 248 | + | |
| 249 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 250 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 251 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 252 | + // allocates stack space for every case branch when no optimizations are | |
| 253 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 254 | + switch fieldNumber { | |
| 255 | + case 1: try { try decoder.decodeSingularStringField(value: &self.facetAddress) }() | |
| 256 | + case 2: try { try decoder.decodeSingularEnumField(value: &self.action) }() | |
| 257 | + case 3: try { try decoder.decodeRepeatedBytesField(value: &self.functionSelectors) }() | |
| 258 | + default: break | |
| 259 | + } | |
| 260 | + } | |
| 261 | + } | |
| 262 | + | |
| 263 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 264 | + if !self.facetAddress.isEmpty { | |
| 265 | + try visitor.visitSingularStringField(value: self.facetAddress, fieldNumber: 1) | |
| 266 | + } | |
| 267 | + if self.action != .add { | |
| 268 | + try visitor.visitSingularEnumField(value: self.action, fieldNumber: 2) | |
| 269 | + } | |
| 270 | + if !self.functionSelectors.isEmpty { | |
| 271 | + try visitor.visitRepeatedBytesField(value: self.functionSelectors, fieldNumber: 3) | |
| 272 | + } | |
| 273 | + try unknownFields.traverse(visitor: &visitor) | |
| 274 | + } | |
| 275 | + | |
| 276 | + public static func ==(lhs: TW_Barz_Proto_FacetCut, rhs: TW_Barz_Proto_FacetCut) -> Bool { | |
| 277 | + if lhs.facetAddress != rhs.facetAddress {return false} | |
| 278 | + if lhs.action != rhs.action {return false} | |
| 279 | + if lhs.functionSelectors != rhs.functionSelectors {return false} | |
| 280 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 281 | + return true | |
| 282 | + } | |
| 283 | +} | |
| 284 | + | |
| 285 | +extension TW_Barz_Proto_DiamondCutInput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 286 | + public static let protoMessageName: String = _protobuf_package + ".DiamondCutInput" | |
| 287 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 288 | + 1: .standard(proto: "facet_cuts"), | |
| 289 | + 2: .standard(proto: "init_address"), | |
| 290 | + 3: .standard(proto: "init_data"), | |
| 291 | + ] | |
| 292 | + | |
| 293 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 294 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 295 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 296 | + // allocates stack space for every case branch when no optimizations are | |
| 297 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 298 | + switch fieldNumber { | |
| 299 | + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.facetCuts) }() | |
| 300 | + case 2: try { try decoder.decodeSingularStringField(value: &self.initAddress) }() | |
| 301 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.initData) }() | |
| 302 | + default: break | |
| 303 | + } | |
| 304 | + } | |
| 305 | + } | |
| 306 | + | |
| 307 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 308 | + if !self.facetCuts.isEmpty { | |
| 309 | + try visitor.visitRepeatedMessageField(value: self.facetCuts, fieldNumber: 1) | |
| 310 | + } | |
| 311 | + if !self.initAddress.isEmpty { | |
| 312 | + try visitor.visitSingularStringField(value: self.initAddress, fieldNumber: 2) | |
| 313 | + } | |
| 314 | + if !self.initData.isEmpty { | |
| 315 | + try visitor.visitSingularBytesField(value: self.initData, fieldNumber: 3) | |
| 316 | + } | |
| 317 | + try unknownFields.traverse(visitor: &visitor) | |
| 318 | + } | |
| 319 | + | |
| 320 | + public static func ==(lhs: TW_Barz_Proto_DiamondCutInput, rhs: TW_Barz_Proto_DiamondCutInput) -> Bool { | |
| 321 | + if lhs.facetCuts != rhs.facetCuts {return false} | |
| 322 | + if lhs.initAddress != rhs.initAddress {return false} | |
| 323 | + if lhs.initData != rhs.initData {return false} | |
| 324 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 325 | + return true | |
| 326 | + } | |
| 327 | +} | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Binance+Proto.swift
+25 −0
@@ -0,0 +1,25 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// SPDX-License-Identifier: Apache-2.0 | |
| 4 | +// | |
| 5 | +// Copyright © 2017 Trust Wallet. | |
| 6 | + | |
| 7 | +public typealias BinanceTransaction = TW_Binance_Proto_Transaction | |
| 8 | +public typealias BinanceSignature = TW_Binance_Proto_Signature | |
| 9 | +public typealias BinanceTradeOrder = TW_Binance_Proto_TradeOrder | |
| 10 | +public typealias BinanceCancelTradeOrder = TW_Binance_Proto_CancelTradeOrder | |
| 11 | +public typealias BinanceSendOrder = TW_Binance_Proto_SendOrder | |
| 12 | +public typealias BinanceHTLTOrder = TW_Binance_Proto_HTLTOrder | |
| 13 | +public typealias BinanceDepositHTLTOrder = TW_Binance_Proto_DepositHTLTOrder | |
| 14 | +public typealias BinanceClaimHTLOrder = TW_Binance_Proto_ClaimHTLOrder | |
| 15 | +public typealias BinanceRefundHTLTOrder = TW_Binance_Proto_RefundHTLTOrder | |
| 16 | +public typealias BinanceTransferOut = TW_Binance_Proto_TransferOut | |
| 17 | +public typealias BinanceSideChainDelegate = TW_Binance_Proto_SideChainDelegate | |
| 18 | +public typealias BinanceSideChainRedelegate = TW_Binance_Proto_SideChainRedelegate | |
| 19 | +public typealias BinanceSideChainUndelegate = TW_Binance_Proto_SideChainUndelegate | |
| 20 | +public typealias BinanceSideChainStakeMigration = TW_Binance_Proto_SideChainStakeMigration | |
| 21 | +public typealias BinanceTimeLockOrder = TW_Binance_Proto_TimeLockOrder | |
| 22 | +public typealias BinanceTimeRelockOrder = TW_Binance_Proto_TimeRelockOrder | |
| 23 | +public typealias BinanceTimeUnlockOrder = TW_Binance_Proto_TimeUnlockOrder | |
| 24 | +public typealias BinanceSigningInput = TW_Binance_Proto_SigningInput | |
| 25 | +public typealias BinanceSigningOutput = TW_Binance_Proto_SigningOutput | |
added
vendor/WalletCoreSPM/Sources/WalletCore/Generated/Protobuf/Binance.pb.swift
+2171 −0
@@ -0,0 +1,2191 @@ | ||
| 1 | +import WalletCoreC | |
| 2 | +import Foundation | |
| 3 | +// DO NOT EDIT. | |
| 4 | +// swift-format-ignore-file | |
| 5 | +// | |
| 6 | +// Generated by the Swift generator plugin for the protocol buffer compiler. | |
| 7 | +// Source: Binance.proto | |
| 8 | +// | |
| 9 | +// For information on using the generated types, please see the documentation: | |
| 10 | +// https://github.com/apple/swift-protobuf/ | |
| 11 | + | |
| 12 | +import Foundation | |
| 13 | +import SwiftProtobuf | |
| 14 | + | |
| 15 | +// If the compiler emits an error on this type, it is because this file | |
| 16 | +// was generated by a version of the `protoc` Swift plug-in that is | |
| 17 | +// incompatible with the version of SwiftProtobuf.to which you are linking. | |
| 18 | +// Please ensure that you are building against the same version of the API | |
| 19 | +// that was used to generate this file. | |
| 20 | +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { | |
| 21 | + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} | |
| 22 | + typealias Version = _2 | |
| 23 | +} | |
| 24 | + | |
| 25 | +/// Transaction structure, used internally | |
| 26 | +public struct TW_Binance_Proto_Transaction { | |
| 27 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 28 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 29 | + // methods supported on all messages. | |
| 30 | + | |
| 31 | + /// array of size 1, containing the transaction message, which are one of the transaction type below | |
| 32 | + public var msgs: [Data] = [] | |
| 33 | + | |
| 34 | + /// array of size 1, containing the standard signature structure of the transaction sender | |
| 35 | + public var signatures: [Data] = [] | |
| 36 | + | |
| 37 | + /// a short sentence of remark for the transaction, only for `Transfer` transactions. | |
| 38 | + public var memo: String = String() | |
| 39 | + | |
| 40 | + /// an identifier for tools triggering this transaction, set to zero if unwilling to disclose. | |
| 41 | + public var source: Int64 = 0 | |
| 42 | + | |
| 43 | + /// reserved for future use | |
| 44 | + public var data: Data = Data() | |
| 45 | + | |
| 46 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 47 | + | |
| 48 | + public init() {} | |
| 49 | +} | |
| 50 | + | |
| 51 | +/// Signature structure, used internally | |
| 52 | +public struct TW_Binance_Proto_Signature { | |
| 53 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 54 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 55 | + // methods supported on all messages. | |
| 56 | + | |
| 57 | + /// public key bytes of the signer address | |
| 58 | + public var pubKey: Data = Data() | |
| 59 | + | |
| 60 | + /// signature bytes, please check chain access section for signature generation | |
| 61 | + public var signature: Data = Data() | |
| 62 | + | |
| 63 | + /// another identifier of signer, which can be read from chain by account REST API or RPC | |
| 64 | + public var accountNumber: Int64 = 0 | |
| 65 | + | |
| 66 | + /// sequence number for the next transaction | |
| 67 | + public var sequence: Int64 = 0 | |
| 68 | + | |
| 69 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 70 | + | |
| 71 | + public init() {} | |
| 72 | +} | |
| 73 | + | |
| 74 | +/// Message for Trade order | |
| 75 | +public struct TW_Binance_Proto_TradeOrder { | |
| 76 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 77 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 78 | + // methods supported on all messages. | |
| 79 | + | |
| 80 | + /// originating address | |
| 81 | + public var sender: Data = Data() | |
| 82 | + | |
| 83 | + /// order id, optional | |
| 84 | + public var id: String = String() | |
| 85 | + | |
| 86 | + /// symbol for trading pair in full name of the tokens | |
| 87 | + public var symbol: String = String() | |
| 88 | + | |
| 89 | + /// only accept 2 for now, meaning limit order | |
| 90 | + public var ordertype: Int64 = 0 | |
| 91 | + | |
| 92 | + /// 1 for buy and 2 for sell | |
| 93 | + public var side: Int64 = 0 | |
| 94 | + | |
| 95 | + /// price of the order, which is the real price multiplied by 1e8 (10^8) and rounded to integer | |
| 96 | + public var price: Int64 = 0 | |
| 97 | + | |
| 98 | + /// quantity of the order, which is the real price multiplied by 1e8 (10^8) and rounded to integer | |
| 99 | + public var quantity: Int64 = 0 | |
| 100 | + | |
| 101 | + /// 1 for Good Till Expire(GTE) order and 3 for Immediate Or Cancel (IOC) | |
| 102 | + public var timeinforce: Int64 = 0 | |
| 103 | + | |
| 104 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 105 | + | |
| 106 | + public init() {} | |
| 107 | +} | |
| 108 | + | |
| 109 | +/// Message for CancelTrade order | |
| 110 | +public struct TW_Binance_Proto_CancelTradeOrder { | |
| 111 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 112 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 113 | + // methods supported on all messages. | |
| 114 | + | |
| 115 | + /// originating address | |
| 116 | + public var sender: Data = Data() | |
| 117 | + | |
| 118 | + /// symbol for trading pair in full name of the tokens | |
| 119 | + public var symbol: String = String() | |
| 120 | + | |
| 121 | + /// order id to cancel | |
| 122 | + public var refid: String = String() | |
| 123 | + | |
| 124 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 125 | + | |
| 126 | + public init() {} | |
| 127 | +} | |
| 128 | + | |
| 129 | +/// Message for Send order | |
| 130 | +public struct TW_Binance_Proto_SendOrder { | |
| 131 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 132 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 133 | + // methods supported on all messages. | |
| 134 | + | |
| 135 | + /// Send inputs | |
| 136 | + public var inputs: [TW_Binance_Proto_SendOrder.Input] = [] | |
| 137 | + | |
| 138 | + /// Send outputs | |
| 139 | + public var outputs: [TW_Binance_Proto_SendOrder.Output] = [] | |
| 140 | + | |
| 141 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 142 | + | |
| 143 | + /// A token amount, symbol-amount pair. Could be moved out of SendOrder; kept here for backward compatibility. | |
| 144 | + public struct Token { | |
| 145 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 146 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 147 | + // methods supported on all messages. | |
| 148 | + | |
| 149 | + /// Token ID | |
| 150 | + public var denom: String = String() | |
| 151 | + | |
| 152 | + /// Amount | |
| 153 | + public var amount: Int64 = 0 | |
| 154 | + | |
| 155 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 156 | + | |
| 157 | + public init() {} | |
| 158 | + } | |
| 159 | + | |
| 160 | + /// Transaction input | |
| 161 | + public struct Input { | |
| 162 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 163 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 164 | + // methods supported on all messages. | |
| 165 | + | |
| 166 | + /// source address | |
| 167 | + public var address: Data = Data() | |
| 168 | + | |
| 169 | + /// input coin amounts | |
| 170 | + public var coins: [TW_Binance_Proto_SendOrder.Token] = [] | |
| 171 | + | |
| 172 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 173 | + | |
| 174 | + public init() {} | |
| 175 | + } | |
| 176 | + | |
| 177 | + /// Transaction output | |
| 178 | + public struct Output { | |
| 179 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 180 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 181 | + // methods supported on all messages. | |
| 182 | + | |
| 183 | + /// destination address | |
| 184 | + public var address: Data = Data() | |
| 185 | + | |
| 186 | + /// output coin amounts | |
| 187 | + public var coins: [TW_Binance_Proto_SendOrder.Token] = [] | |
| 188 | + | |
| 189 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 190 | + | |
| 191 | + public init() {} | |
| 192 | + } | |
| 193 | + | |
| 194 | + public init() {} | |
| 195 | +} | |
| 196 | + | |
| 197 | +/// Message for HashTimeLock order | |
| 198 | +public struct TW_Binance_Proto_HTLTOrder { | |
| 199 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 200 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 201 | + // methods supported on all messages. | |
| 202 | + | |
| 203 | + /// signer address | |
| 204 | + public var from: Data = Data() | |
| 205 | + | |
| 206 | + /// recipient address | |
| 207 | + public var to: Data = Data() | |
| 208 | + | |
| 209 | + /// source on other chain, optional | |
| 210 | + public var recipientOtherChain: String = String() | |
| 211 | + | |
| 212 | + /// recipient on other chain, optional | |
| 213 | + public var senderOtherChain: String = String() | |
| 214 | + | |
| 215 | + /// hash of a random number and timestamp, based on SHA256 | |
| 216 | + public var randomNumberHash: Data = Data() | |
| 217 | + | |
| 218 | + /// timestamp | |
| 219 | + public var timestamp: Int64 = 0 | |
| 220 | + | |
| 221 | + /// amounts | |
| 222 | + public var amount: [TW_Binance_Proto_SendOrder.Token] = [] | |
| 223 | + | |
| 224 | + /// expected gained token on the other chain | |
| 225 | + public var expectedIncome: String = String() | |
| 226 | + | |
| 227 | + /// period expressed in block heights | |
| 228 | + public var heightSpan: Int64 = 0 | |
| 229 | + | |
| 230 | + /// set for cross-chain send | |
| 231 | + public var crossChain: Bool = false | |
| 232 | + | |
| 233 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 234 | + | |
| 235 | + public init() {} | |
| 236 | +} | |
| 237 | + | |
| 238 | +/// Message for Deposit HTLT order | |
| 239 | +public struct TW_Binance_Proto_DepositHTLTOrder { | |
| 240 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 241 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 242 | + // methods supported on all messages. | |
| 243 | + | |
| 244 | + /// signer address | |
| 245 | + public var from: Data = Data() | |
| 246 | + | |
| 247 | + /// amounts | |
| 248 | + public var amount: [TW_Binance_Proto_SendOrder.Token] = [] | |
| 249 | + | |
| 250 | + /// swap ID | |
| 251 | + public var swapID: Data = Data() | |
| 252 | + | |
| 253 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 254 | + | |
| 255 | + public init() {} | |
| 256 | +} | |
| 257 | + | |
| 258 | +/// Message for Claim HTLT order | |
| 259 | +public struct TW_Binance_Proto_ClaimHTLOrder { | |
| 260 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 261 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 262 | + // methods supported on all messages. | |
| 263 | + | |
| 264 | + /// signer address | |
| 265 | + public var from: Data = Data() | |
| 266 | + | |
| 267 | + /// swap ID | |
| 268 | + public var swapID: Data = Data() | |
| 269 | + | |
| 270 | + /// random number input | |
| 271 | + public var randomNumber: Data = Data() | |
| 272 | + | |
| 273 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 274 | + | |
| 275 | + public init() {} | |
| 276 | +} | |
| 277 | + | |
| 278 | +/// Message for Refund HTLT order | |
| 279 | +public struct TW_Binance_Proto_RefundHTLTOrder { | |
| 280 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 281 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 282 | + // methods supported on all messages. | |
| 283 | + | |
| 284 | + /// signer address | |
| 285 | + public var from: Data = Data() | |
| 286 | + | |
| 287 | + /// swap ID | |
| 288 | + public var swapID: Data = Data() | |
| 289 | + | |
| 290 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 291 | + | |
| 292 | + public init() {} | |
| 293 | +} | |
| 294 | + | |
| 295 | +/// Transfer | |
| 296 | +public struct TW_Binance_Proto_TransferOut { | |
| 297 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 298 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 299 | + // methods supported on all messages. | |
| 300 | + | |
| 301 | + /// source address | |
| 302 | + public var from: Data = Data() | |
| 303 | + | |
| 304 | + /// recipient address | |
| 305 | + public var to: Data = Data() | |
| 306 | + | |
| 307 | + /// transfer amount | |
| 308 | + public var amount: TW_Binance_Proto_SendOrder.Token { | |
| 309 | + get {return _amount ?? TW_Binance_Proto_SendOrder.Token()} | |
| 310 | + set {_amount = newValue} | |
| 311 | + } | |
| 312 | + /// Returns true if `amount` has been explicitly set. | |
| 313 | + public var hasAmount: Bool {return self._amount != nil} | |
| 314 | + /// Clears the value of `amount`. Subsequent reads from it will return its default value. | |
| 315 | + public mutating func clearAmount() {self._amount = nil} | |
| 316 | + | |
| 317 | + /// expiration time | |
| 318 | + public var expireTime: Int64 = 0 | |
| 319 | + | |
| 320 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 321 | + | |
| 322 | + public init() {} | |
| 323 | + | |
| 324 | + fileprivate var _amount: TW_Binance_Proto_SendOrder.Token? = nil | |
| 325 | +} | |
| 326 | + | |
| 327 | +public struct TW_Binance_Proto_SideChainDelegate { | |
| 328 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 329 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 330 | + // methods supported on all messages. | |
| 331 | + | |
| 332 | + public var delegatorAddr: Data = Data() | |
| 333 | + | |
| 334 | + public var validatorAddr: Data = Data() | |
| 335 | + | |
| 336 | + public var delegation: TW_Binance_Proto_SendOrder.Token { | |
| 337 | + get {return _delegation ?? TW_Binance_Proto_SendOrder.Token()} | |
| 338 | + set {_delegation = newValue} | |
| 339 | + } | |
| 340 | + /// Returns true if `delegation` has been explicitly set. | |
| 341 | + public var hasDelegation: Bool {return self._delegation != nil} | |
| 342 | + /// Clears the value of `delegation`. Subsequent reads from it will return its default value. | |
| 343 | + public mutating func clearDelegation() {self._delegation = nil} | |
| 344 | + | |
| 345 | + public var chainID: String = String() | |
| 346 | + | |
| 347 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 348 | + | |
| 349 | + public init() {} | |
| 350 | + | |
| 351 | + fileprivate var _delegation: TW_Binance_Proto_SendOrder.Token? = nil | |
| 352 | +} | |
| 353 | + | |
| 354 | +public struct TW_Binance_Proto_SideChainRedelegate { | |
| 355 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 356 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 357 | + // methods supported on all messages. | |
| 358 | + | |
| 359 | + public var delegatorAddr: Data = Data() | |
| 360 | + | |
| 361 | + public var validatorSrcAddr: Data = Data() | |
| 362 | + | |
| 363 | + public var validatorDstAddr: Data = Data() | |
| 364 | + | |
| 365 | + public var amount: TW_Binance_Proto_SendOrder.Token { | |
| 366 | + get {return _amount ?? TW_Binance_Proto_SendOrder.Token()} | |
| 367 | + set {_amount = newValue} | |
| 368 | + } | |
| 369 | + /// Returns true if `amount` has been explicitly set. | |
| 370 | + public var hasAmount: Bool {return self._amount != nil} | |
| 371 | + /// Clears the value of `amount`. Subsequent reads from it will return its default value. | |
| 372 | + public mutating func clearAmount() {self._amount = nil} | |
| 373 | + | |
| 374 | + public var chainID: String = String() | |
| 375 | + | |
| 376 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 377 | + | |
| 378 | + public init() {} | |
| 379 | + | |
| 380 | + fileprivate var _amount: TW_Binance_Proto_SendOrder.Token? = nil | |
| 381 | +} | |
| 382 | + | |
| 383 | +public struct TW_Binance_Proto_SideChainUndelegate { | |
| 384 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 385 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 386 | + // methods supported on all messages. | |
| 387 | + | |
| 388 | + public var delegatorAddr: Data = Data() | |
| 389 | + | |
| 390 | + public var validatorAddr: Data = Data() | |
| 391 | + | |
| 392 | + public var amount: TW_Binance_Proto_SendOrder.Token { | |
| 393 | + get {return _amount ?? TW_Binance_Proto_SendOrder.Token()} | |
| 394 | + set {_amount = newValue} | |
| 395 | + } | |
| 396 | + /// Returns true if `amount` has been explicitly set. | |
| 397 | + public var hasAmount: Bool {return self._amount != nil} | |
| 398 | + /// Clears the value of `amount`. Subsequent reads from it will return its default value. | |
| 399 | + public mutating func clearAmount() {self._amount = nil} | |
| 400 | + | |
| 401 | + public var chainID: String = String() | |
| 402 | + | |
| 403 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 404 | + | |
| 405 | + public init() {} | |
| 406 | + | |
| 407 | + fileprivate var _amount: TW_Binance_Proto_SendOrder.Token? = nil | |
| 408 | +} | |
| 409 | + | |
| 410 | +/// Message for BNB Beacon Chain -> BSC Stake Migration. | |
| 411 | +/// https://github.com/bnb-chain/javascript-sdk/blob/26f6db8b67326e6214e74203ff90c89777b592a1/src/types/msg/stake/stakeMigrationMsg.ts#L13-L18 | |
| 412 | +public struct TW_Binance_Proto_SideChainStakeMigration { | |
| 413 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 414 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 415 | + // methods supported on all messages. | |
| 416 | + | |
| 417 | + public var validatorSrcAddr: Data = Data() | |
| 418 | + | |
| 419 | + public var validatorDstAddr: Data = Data() | |
| 420 | + | |
| 421 | + public var delegatorAddr: Data = Data() | |
| 422 | + | |
| 423 | + public var refundAddr: Data = Data() | |
| 424 | + | |
| 425 | + public var amount: TW_Binance_Proto_SendOrder.Token { | |
| 426 | + get {return _amount ?? TW_Binance_Proto_SendOrder.Token()} | |
| 427 | + set {_amount = newValue} | |
| 428 | + } | |
| 429 | + /// Returns true if `amount` has been explicitly set. | |
| 430 | + public var hasAmount: Bool {return self._amount != nil} | |
| 431 | + /// Clears the value of `amount`. Subsequent reads from it will return its default value. | |
| 432 | + public mutating func clearAmount() {self._amount = nil} | |
| 433 | + | |
| 434 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 435 | + | |
| 436 | + public init() {} | |
| 437 | + | |
| 438 | + fileprivate var _amount: TW_Binance_Proto_SendOrder.Token? = nil | |
| 439 | +} | |
| 440 | + | |
| 441 | +/// Message for TimeLock order | |
| 442 | +public struct TW_Binance_Proto_TimeLockOrder { | |
| 443 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 444 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 445 | + // methods supported on all messages. | |
| 446 | + | |
| 447 | + /// owner address | |
| 448 | + public var fromAddress: Data = Data() | |
| 449 | + | |
| 450 | + /// Description (optional) | |
| 451 | + public var description_p: String = String() | |
| 452 | + | |
| 453 | + /// Array of symbol/amount pairs. see SDK https://github.com/binance-chain/javascript-sdk/blob/master/docs/api-docs/classes/tokenmanagement.md#timelock | |
| 454 | + public var amount: [TW_Binance_Proto_SendOrder.Token] = [] | |
| 455 | + | |
| 456 | + /// lock time | |
| 457 | + public var lockTime: Int64 = 0 | |
| 458 | + | |
| 459 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 460 | + | |
| 461 | + public init() {} | |
| 462 | +} | |
| 463 | + | |
| 464 | +/// Message for TimeRelock order | |
| 465 | +public struct TW_Binance_Proto_TimeRelockOrder { | |
| 466 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 467 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 468 | + // methods supported on all messages. | |
| 469 | + | |
| 470 | + /// owner address | |
| 471 | + public var fromAddress: Data = Data() | |
| 472 | + | |
| 473 | + /// order ID | |
| 474 | + public var id: Int64 = 0 | |
| 475 | + | |
| 476 | + /// Description (optional) | |
| 477 | + public var description_p: String = String() | |
| 478 | + | |
| 479 | + /// Array of symbol/amount pairs. | |
| 480 | + public var amount: [TW_Binance_Proto_SendOrder.Token] = [] | |
| 481 | + | |
| 482 | + /// lock time | |
| 483 | + public var lockTime: Int64 = 0 | |
| 484 | + | |
| 485 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 486 | + | |
| 487 | + public init() {} | |
| 488 | +} | |
| 489 | + | |
| 490 | +/// Message for TimeUnlock order | |
| 491 | +public struct TW_Binance_Proto_TimeUnlockOrder { | |
| 492 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 493 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 494 | + // methods supported on all messages. | |
| 495 | + | |
| 496 | + /// owner address | |
| 497 | + public var fromAddress: Data = Data() | |
| 498 | + | |
| 499 | + /// order ID | |
| 500 | + public var id: Int64 = 0 | |
| 501 | + | |
| 502 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 503 | + | |
| 504 | + public init() {} | |
| 505 | +} | |
| 506 | + | |
| 507 | +/// Input data necessary to create a signed transaction. | |
| 508 | +public struct TW_Binance_Proto_SigningInput { | |
| 509 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 510 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 511 | + // methods supported on all messages. | |
| 512 | + | |
| 513 | + /// Chain ID | |
| 514 | + public var chainID: String = String() | |
| 515 | + | |
| 516 | + /// Source account number | |
| 517 | + public var accountNumber: Int64 = 0 | |
| 518 | + | |
| 519 | + /// Sequence number (account specific) | |
| 520 | + public var sequence: Int64 = 0 | |
| 521 | + | |
| 522 | + /// Transaction source, see https://github.com/bnb-chain/BEPs/blob/master/BEP10.md | |
| 523 | + /// Some important values: | |
| 524 | + /// 0: Default source value (e.g. for Binance Chain Command Line, or SDKs) | |
| 525 | + /// 1: Binance DEX Web Wallet | |
| 526 | + /// 2: Trust Wallet | |
| 527 | + public var source: Int64 = 0 | |
| 528 | + | |
| 529 | + /// Optional memo | |
| 530 | + public var memo: String = String() | |
| 531 | + | |
| 532 | + /// The secret private key used for signing (32 bytes). | |
| 533 | + public var privateKey: Data = Data() | |
| 534 | + | |
| 535 | + /// Payload message | |
| 536 | + public var orderOneof: TW_Binance_Proto_SigningInput.OneOf_OrderOneof? = nil | |
| 537 | + | |
| 538 | + public var tradeOrder: TW_Binance_Proto_TradeOrder { | |
| 539 | + get { | |
| 540 | + if case .tradeOrder(let v)? = orderOneof {return v} | |
| 541 | + return TW_Binance_Proto_TradeOrder() | |
| 542 | + } | |
| 543 | + set {orderOneof = .tradeOrder(newValue)} | |
| 544 | + } | |
| 545 | + | |
| 546 | + public var cancelTradeOrder: TW_Binance_Proto_CancelTradeOrder { | |
| 547 | + get { | |
| 548 | + if case .cancelTradeOrder(let v)? = orderOneof {return v} | |
| 549 | + return TW_Binance_Proto_CancelTradeOrder() | |
| 550 | + } | |
| 551 | + set {orderOneof = .cancelTradeOrder(newValue)} | |
| 552 | + } | |
| 553 | + | |
| 554 | + public var sendOrder: TW_Binance_Proto_SendOrder { | |
| 555 | + get { | |
| 556 | + if case .sendOrder(let v)? = orderOneof {return v} | |
| 557 | + return TW_Binance_Proto_SendOrder() | |
| 558 | + } | |
| 559 | + set {orderOneof = .sendOrder(newValue)} | |
| 560 | + } | |
| 561 | + | |
| 562 | + public var htltOrder: TW_Binance_Proto_HTLTOrder { | |
| 563 | + get { | |
| 564 | + if case .htltOrder(let v)? = orderOneof {return v} | |
| 565 | + return TW_Binance_Proto_HTLTOrder() | |
| 566 | + } | |
| 567 | + set {orderOneof = .htltOrder(newValue)} | |
| 568 | + } | |
| 569 | + | |
| 570 | + public var depositHtltOrder: TW_Binance_Proto_DepositHTLTOrder { | |
| 571 | + get { | |
| 572 | + if case .depositHtltOrder(let v)? = orderOneof {return v} | |
| 573 | + return TW_Binance_Proto_DepositHTLTOrder() | |
| 574 | + } | |
| 575 | + set {orderOneof = .depositHtltOrder(newValue)} | |
| 576 | + } | |
| 577 | + | |
| 578 | + public var claimHtltOrder: TW_Binance_Proto_ClaimHTLOrder { | |
| 579 | + get { | |
| 580 | + if case .claimHtltOrder(let v)? = orderOneof {return v} | |
| 581 | + return TW_Binance_Proto_ClaimHTLOrder() | |
| 582 | + } | |
| 583 | + set {orderOneof = .claimHtltOrder(newValue)} | |
| 584 | + } | |
| 585 | + | |
| 586 | + public var refundHtltOrder: TW_Binance_Proto_RefundHTLTOrder { | |
| 587 | + get { | |
| 588 | + if case .refundHtltOrder(let v)? = orderOneof {return v} | |
| 589 | + return TW_Binance_Proto_RefundHTLTOrder() | |
| 590 | + } | |
| 591 | + set {orderOneof = .refundHtltOrder(newValue)} | |
| 592 | + } | |
| 593 | + | |
| 594 | + public var transferOutOrder: TW_Binance_Proto_TransferOut { | |
| 595 | + get { | |
| 596 | + if case .transferOutOrder(let v)? = orderOneof {return v} | |
| 597 | + return TW_Binance_Proto_TransferOut() | |
| 598 | + } | |
| 599 | + set {orderOneof = .transferOutOrder(newValue)} | |
| 600 | + } | |
| 601 | + | |
| 602 | + public var sideDelegateOrder: TW_Binance_Proto_SideChainDelegate { | |
| 603 | + get { | |
| 604 | + if case .sideDelegateOrder(let v)? = orderOneof {return v} | |
| 605 | + return TW_Binance_Proto_SideChainDelegate() | |
| 606 | + } | |
| 607 | + set {orderOneof = .sideDelegateOrder(newValue)} | |
| 608 | + } | |
| 609 | + | |
| 610 | + public var sideRedelegateOrder: TW_Binance_Proto_SideChainRedelegate { | |
| 611 | + get { | |
| 612 | + if case .sideRedelegateOrder(let v)? = orderOneof {return v} | |
| 613 | + return TW_Binance_Proto_SideChainRedelegate() | |
| 614 | + } | |
| 615 | + set {orderOneof = .sideRedelegateOrder(newValue)} | |
| 616 | + } | |
| 617 | + | |
| 618 | + public var sideUndelegateOrder: TW_Binance_Proto_SideChainUndelegate { | |
| 619 | + get { | |
| 620 | + if case .sideUndelegateOrder(let v)? = orderOneof {return v} | |
| 621 | + return TW_Binance_Proto_SideChainUndelegate() | |
| 622 | + } | |
| 623 | + set {orderOneof = .sideUndelegateOrder(newValue)} | |
| 624 | + } | |
| 625 | + | |
| 626 | + public var timeLockOrder: TW_Binance_Proto_TimeLockOrder { | |
| 627 | + get { | |
| 628 | + if case .timeLockOrder(let v)? = orderOneof {return v} | |
| 629 | + return TW_Binance_Proto_TimeLockOrder() | |
| 630 | + } | |
| 631 | + set {orderOneof = .timeLockOrder(newValue)} | |
| 632 | + } | |
| 633 | + | |
| 634 | + public var timeRelockOrder: TW_Binance_Proto_TimeRelockOrder { | |
| 635 | + get { | |
| 636 | + if case .timeRelockOrder(let v)? = orderOneof {return v} | |
| 637 | + return TW_Binance_Proto_TimeRelockOrder() | |
| 638 | + } | |
| 639 | + set {orderOneof = .timeRelockOrder(newValue)} | |
| 640 | + } | |
| 641 | + | |
| 642 | + public var timeUnlockOrder: TW_Binance_Proto_TimeUnlockOrder { | |
| 643 | + get { | |
| 644 | + if case .timeUnlockOrder(let v)? = orderOneof {return v} | |
| 645 | + return TW_Binance_Proto_TimeUnlockOrder() | |
| 646 | + } | |
| 647 | + set {orderOneof = .timeUnlockOrder(newValue)} | |
| 648 | + } | |
| 649 | + | |
| 650 | + public var sideStakeMigrationOrder: TW_Binance_Proto_SideChainStakeMigration { | |
| 651 | + get { | |
| 652 | + if case .sideStakeMigrationOrder(let v)? = orderOneof {return v} | |
| 653 | + return TW_Binance_Proto_SideChainStakeMigration() | |
| 654 | + } | |
| 655 | + set {orderOneof = .sideStakeMigrationOrder(newValue)} | |
| 656 | + } | |
| 657 | + | |
| 658 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 659 | + | |
| 660 | + /// Payload message | |
| 661 | + public enum OneOf_OrderOneof: Equatable { | |
| 662 | + case tradeOrder(TW_Binance_Proto_TradeOrder) | |
| 663 | + case cancelTradeOrder(TW_Binance_Proto_CancelTradeOrder) | |
| 664 | + case sendOrder(TW_Binance_Proto_SendOrder) | |
| 665 | + case htltOrder(TW_Binance_Proto_HTLTOrder) | |
| 666 | + case depositHtltOrder(TW_Binance_Proto_DepositHTLTOrder) | |
| 667 | + case claimHtltOrder(TW_Binance_Proto_ClaimHTLOrder) | |
| 668 | + case refundHtltOrder(TW_Binance_Proto_RefundHTLTOrder) | |
| 669 | + case transferOutOrder(TW_Binance_Proto_TransferOut) | |
| 670 | + case sideDelegateOrder(TW_Binance_Proto_SideChainDelegate) | |
| 671 | + case sideRedelegateOrder(TW_Binance_Proto_SideChainRedelegate) | |
| 672 | + case sideUndelegateOrder(TW_Binance_Proto_SideChainUndelegate) | |
| 673 | + case timeLockOrder(TW_Binance_Proto_TimeLockOrder) | |
| 674 | + case timeRelockOrder(TW_Binance_Proto_TimeRelockOrder) | |
| 675 | + case timeUnlockOrder(TW_Binance_Proto_TimeUnlockOrder) | |
| 676 | + case sideStakeMigrationOrder(TW_Binance_Proto_SideChainStakeMigration) | |
| 677 | + | |
| 678 | + #if !swift(>=4.1) | |
| 679 | + public static func ==(lhs: TW_Binance_Proto_SigningInput.OneOf_OrderOneof, rhs: TW_Binance_Proto_SigningInput.OneOf_OrderOneof) -> Bool { | |
| 680 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 681 | + // allocates stack space for every case branch when no optimizations are | |
| 682 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 683 | + switch (lhs, rhs) { | |
| 684 | + case (.tradeOrder, .tradeOrder): return { | |
| 685 | + guard case .tradeOrder(let l) = lhs, case .tradeOrder(let r) = rhs else { preconditionFailure() } | |
| 686 | + return l == r | |
| 687 | + }() | |
| 688 | + case (.cancelTradeOrder, .cancelTradeOrder): return { | |
| 689 | + guard case .cancelTradeOrder(let l) = lhs, case .cancelTradeOrder(let r) = rhs else { preconditionFailure() } | |
| 690 | + return l == r | |
| 691 | + }() | |
| 692 | + case (.sendOrder, .sendOrder): return { | |
| 693 | + guard case .sendOrder(let l) = lhs, case .sendOrder(let r) = rhs else { preconditionFailure() } | |
| 694 | + return l == r | |
| 695 | + }() | |
| 696 | + case (.htltOrder, .htltOrder): return { | |
| 697 | + guard case .htltOrder(let l) = lhs, case .htltOrder(let r) = rhs else { preconditionFailure() } | |
| 698 | + return l == r | |
| 699 | + }() | |
| 700 | + case (.depositHtltOrder, .depositHtltOrder): return { | |
| 701 | + guard case .depositHtltOrder(let l) = lhs, case .depositHtltOrder(let r) = rhs else { preconditionFailure() } | |
| 702 | + return l == r | |
| 703 | + }() | |
| 704 | + case (.claimHtltOrder, .claimHtltOrder): return { | |
| 705 | + guard case .claimHtltOrder(let l) = lhs, case .claimHtltOrder(let r) = rhs else { preconditionFailure() } | |
| 706 | + return l == r | |
| 707 | + }() | |
| 708 | + case (.refundHtltOrder, .refundHtltOrder): return { | |
| 709 | + guard case .refundHtltOrder(let l) = lhs, case .refundHtltOrder(let r) = rhs else { preconditionFailure() } | |
| 710 | + return l == r | |
| 711 | + }() | |
| 712 | + case (.transferOutOrder, .transferOutOrder): return { | |
| 713 | + guard case .transferOutOrder(let l) = lhs, case .transferOutOrder(let r) = rhs else { preconditionFailure() } | |
| 714 | + return l == r | |
| 715 | + }() | |
| 716 | + case (.sideDelegateOrder, .sideDelegateOrder): return { | |
| 717 | + guard case .sideDelegateOrder(let l) = lhs, case .sideDelegateOrder(let r) = rhs else { preconditionFailure() } | |
| 718 | + return l == r | |
| 719 | + }() | |
| 720 | + case (.sideRedelegateOrder, .sideRedelegateOrder): return { | |
| 721 | + guard case .sideRedelegateOrder(let l) = lhs, case .sideRedelegateOrder(let r) = rhs else { preconditionFailure() } | |
| 722 | + return l == r | |
| 723 | + }() | |
| 724 | + case (.sideUndelegateOrder, .sideUndelegateOrder): return { | |
| 725 | + guard case .sideUndelegateOrder(let l) = lhs, case .sideUndelegateOrder(let r) = rhs else { preconditionFailure() } | |
| 726 | + return l == r | |
| 727 | + }() | |
| 728 | + case (.timeLockOrder, .timeLockOrder): return { | |
| 729 | + guard case .timeLockOrder(let l) = lhs, case .timeLockOrder(let r) = rhs else { preconditionFailure() } | |
| 730 | + return l == r | |
| 731 | + }() | |
| 732 | + case (.timeRelockOrder, .timeRelockOrder): return { | |
| 733 | + guard case .timeRelockOrder(let l) = lhs, case .timeRelockOrder(let r) = rhs else { preconditionFailure() } | |
| 734 | + return l == r | |
| 735 | + }() | |
| 736 | + case (.timeUnlockOrder, .timeUnlockOrder): return { | |
| 737 | + guard case .timeUnlockOrder(let l) = lhs, case .timeUnlockOrder(let r) = rhs else { preconditionFailure() } | |
| 738 | + return l == r | |
| 739 | + }() | |
| 740 | + case (.sideStakeMigrationOrder, .sideStakeMigrationOrder): return { | |
| 741 | + guard case .sideStakeMigrationOrder(let l) = lhs, case .sideStakeMigrationOrder(let r) = rhs else { preconditionFailure() } | |
| 742 | + return l == r | |
| 743 | + }() | |
| 744 | + default: return false | |
| 745 | + } | |
| 746 | + } | |
| 747 | + #endif | |
| 748 | + } | |
| 749 | + | |
| 750 | + public init() {} | |
| 751 | +} | |
| 752 | + | |
| 753 | +/// Result containing the signed and encoded transaction. | |
| 754 | +public struct TW_Binance_Proto_SigningOutput { | |
| 755 | + // SwiftProtobuf.Message conformance is added in an extension below. See the | |
| 756 | + // `Message` and `Message+*Additions` files in the SwiftProtobuf.library for | |
| 757 | + // methods supported on all messages. | |
| 758 | + | |
| 759 | + /// Signed and encoded transaction bytes. | |
| 760 | + public var encoded: Data = Data() | |
| 761 | + | |
| 762 | + /// OK (=0) or other codes in case of error | |
| 763 | + public var error: TW_Common_Proto_SigningError = .ok | |
| 764 | + | |
| 765 | + /// error description in case of error | |
| 766 | + public var errorMessage: String = String() | |
| 767 | + | |
| 768 | + /// Signature bytes. | |
| 769 | + public var signature: Data = Data() | |
| 770 | + | |
| 771 | + /// Signature JSON string. | |
| 772 | + public var signatureJson: String = String() | |
| 773 | + | |
| 774 | + public var unknownFields = SwiftProtobuf.UnknownStorage() | |
| 775 | + | |
| 776 | + public init() {} | |
| 777 | +} | |
| 778 | + | |
| 779 | +// MARK: - Code below here is support for the SwiftProtobuf.runtime. | |
| 780 | + | |
| 781 | +fileprivate let _protobuf_package = "TW.Binance.Proto" | |
| 782 | + | |
| 783 | +extension TW_Binance_Proto_Transaction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 784 | + public static let protoMessageName: String = _protobuf_package + ".Transaction" | |
| 785 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 786 | + 1: .same(proto: "msgs"), | |
| 787 | + 2: .same(proto: "signatures"), | |
| 788 | + 3: .same(proto: "memo"), | |
| 789 | + 4: .same(proto: "source"), | |
| 790 | + 5: .same(proto: "data"), | |
| 791 | + ] | |
| 792 | + | |
| 793 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 794 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 795 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 796 | + // allocates stack space for every case branch when no optimizations are | |
| 797 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 798 | + switch fieldNumber { | |
| 799 | + case 1: try { try decoder.decodeRepeatedBytesField(value: &self.msgs) }() | |
| 800 | + case 2: try { try decoder.decodeRepeatedBytesField(value: &self.signatures) }() | |
| 801 | + case 3: try { try decoder.decodeSingularStringField(value: &self.memo) }() | |
| 802 | + case 4: try { try decoder.decodeSingularInt64Field(value: &self.source) }() | |
| 803 | + case 5: try { try decoder.decodeSingularBytesField(value: &self.data) }() | |
| 804 | + default: break | |
| 805 | + } | |
| 806 | + } | |
| 807 | + } | |
| 808 | + | |
| 809 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 810 | + if !self.msgs.isEmpty { | |
| 811 | + try visitor.visitRepeatedBytesField(value: self.msgs, fieldNumber: 1) | |
| 812 | + } | |
| 813 | + if !self.signatures.isEmpty { | |
| 814 | + try visitor.visitRepeatedBytesField(value: self.signatures, fieldNumber: 2) | |
| 815 | + } | |
| 816 | + if !self.memo.isEmpty { | |
| 817 | + try visitor.visitSingularStringField(value: self.memo, fieldNumber: 3) | |
| 818 | + } | |
| 819 | + if self.source != 0 { | |
| 820 | + try visitor.visitSingularInt64Field(value: self.source, fieldNumber: 4) | |
| 821 | + } | |
| 822 | + if !self.data.isEmpty { | |
| 823 | + try visitor.visitSingularBytesField(value: self.data, fieldNumber: 5) | |
| 824 | + } | |
| 825 | + try unknownFields.traverse(visitor: &visitor) | |
| 826 | + } | |
| 827 | + | |
| 828 | + public static func ==(lhs: TW_Binance_Proto_Transaction, rhs: TW_Binance_Proto_Transaction) -> Bool { | |
| 829 | + if lhs.msgs != rhs.msgs {return false} | |
| 830 | + if lhs.signatures != rhs.signatures {return false} | |
| 831 | + if lhs.memo != rhs.memo {return false} | |
| 832 | + if lhs.source != rhs.source {return false} | |
| 833 | + if lhs.data != rhs.data {return false} | |
| 834 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 835 | + return true | |
| 836 | + } | |
| 837 | +} | |
| 838 | + | |
| 839 | +extension TW_Binance_Proto_Signature: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 840 | + public static let protoMessageName: String = _protobuf_package + ".Signature" | |
| 841 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 842 | + 1: .standard(proto: "pub_key"), | |
| 843 | + 2: .same(proto: "signature"), | |
| 844 | + 3: .standard(proto: "account_number"), | |
| 845 | + 4: .same(proto: "sequence"), | |
| 846 | + ] | |
| 847 | + | |
| 848 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 849 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 850 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 851 | + // allocates stack space for every case branch when no optimizations are | |
| 852 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 853 | + switch fieldNumber { | |
| 854 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.pubKey) }() | |
| 855 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.signature) }() | |
| 856 | + case 3: try { try decoder.decodeSingularInt64Field(value: &self.accountNumber) }() | |
| 857 | + case 4: try { try decoder.decodeSingularInt64Field(value: &self.sequence) }() | |
| 858 | + default: break | |
| 859 | + } | |
| 860 | + } | |
| 861 | + } | |
| 862 | + | |
| 863 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 864 | + if !self.pubKey.isEmpty { | |
| 865 | + try visitor.visitSingularBytesField(value: self.pubKey, fieldNumber: 1) | |
| 866 | + } | |
| 867 | + if !self.signature.isEmpty { | |
| 868 | + try visitor.visitSingularBytesField(value: self.signature, fieldNumber: 2) | |
| 869 | + } | |
| 870 | + if self.accountNumber != 0 { | |
| 871 | + try visitor.visitSingularInt64Field(value: self.accountNumber, fieldNumber: 3) | |
| 872 | + } | |
| 873 | + if self.sequence != 0 { | |
| 874 | + try visitor.visitSingularInt64Field(value: self.sequence, fieldNumber: 4) | |
| 875 | + } | |
| 876 | + try unknownFields.traverse(visitor: &visitor) | |
| 877 | + } | |
| 878 | + | |
| 879 | + public static func ==(lhs: TW_Binance_Proto_Signature, rhs: TW_Binance_Proto_Signature) -> Bool { | |
| 880 | + if lhs.pubKey != rhs.pubKey {return false} | |
| 881 | + if lhs.signature != rhs.signature {return false} | |
| 882 | + if lhs.accountNumber != rhs.accountNumber {return false} | |
| 883 | + if lhs.sequence != rhs.sequence {return false} | |
| 884 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 885 | + return true | |
| 886 | + } | |
| 887 | +} | |
| 888 | + | |
| 889 | +extension TW_Binance_Proto_TradeOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 890 | + public static let protoMessageName: String = _protobuf_package + ".TradeOrder" | |
| 891 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 892 | + 1: .same(proto: "sender"), | |
| 893 | + 2: .same(proto: "id"), | |
| 894 | + 3: .same(proto: "symbol"), | |
| 895 | + 4: .same(proto: "ordertype"), | |
| 896 | + 5: .same(proto: "side"), | |
| 897 | + 6: .same(proto: "price"), | |
| 898 | + 7: .same(proto: "quantity"), | |
| 899 | + 8: .same(proto: "timeinforce"), | |
| 900 | + ] | |
| 901 | + | |
| 902 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 903 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 904 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 905 | + // allocates stack space for every case branch when no optimizations are | |
| 906 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 907 | + switch fieldNumber { | |
| 908 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.sender) }() | |
| 909 | + case 2: try { try decoder.decodeSingularStringField(value: &self.id) }() | |
| 910 | + case 3: try { try decoder.decodeSingularStringField(value: &self.symbol) }() | |
| 911 | + case 4: try { try decoder.decodeSingularInt64Field(value: &self.ordertype) }() | |
| 912 | + case 5: try { try decoder.decodeSingularInt64Field(value: &self.side) }() | |
| 913 | + case 6: try { try decoder.decodeSingularInt64Field(value: &self.price) }() | |
| 914 | + case 7: try { try decoder.decodeSingularInt64Field(value: &self.quantity) }() | |
| 915 | + case 8: try { try decoder.decodeSingularInt64Field(value: &self.timeinforce) }() | |
| 916 | + default: break | |
| 917 | + } | |
| 918 | + } | |
| 919 | + } | |
| 920 | + | |
| 921 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 922 | + if !self.sender.isEmpty { | |
| 923 | + try visitor.visitSingularBytesField(value: self.sender, fieldNumber: 1) | |
| 924 | + } | |
| 925 | + if !self.id.isEmpty { | |
| 926 | + try visitor.visitSingularStringField(value: self.id, fieldNumber: 2) | |
| 927 | + } | |
| 928 | + if !self.symbol.isEmpty { | |
| 929 | + try visitor.visitSingularStringField(value: self.symbol, fieldNumber: 3) | |
| 930 | + } | |
| 931 | + if self.ordertype != 0 { | |
| 932 | + try visitor.visitSingularInt64Field(value: self.ordertype, fieldNumber: 4) | |
| 933 | + } | |
| 934 | + if self.side != 0 { | |
| 935 | + try visitor.visitSingularInt64Field(value: self.side, fieldNumber: 5) | |
| 936 | + } | |
| 937 | + if self.price != 0 { | |
| 938 | + try visitor.visitSingularInt64Field(value: self.price, fieldNumber: 6) | |
| 939 | + } | |
| 940 | + if self.quantity != 0 { | |
| 941 | + try visitor.visitSingularInt64Field(value: self.quantity, fieldNumber: 7) | |
| 942 | + } | |
| 943 | + if self.timeinforce != 0 { | |
| 944 | + try visitor.visitSingularInt64Field(value: self.timeinforce, fieldNumber: 8) | |
| 945 | + } | |
| 946 | + try unknownFields.traverse(visitor: &visitor) | |
| 947 | + } | |
| 948 | + | |
| 949 | + public static func ==(lhs: TW_Binance_Proto_TradeOrder, rhs: TW_Binance_Proto_TradeOrder) -> Bool { | |
| 950 | + if lhs.sender != rhs.sender {return false} | |
| 951 | + if lhs.id != rhs.id {return false} | |
| 952 | + if lhs.symbol != rhs.symbol {return false} | |
| 953 | + if lhs.ordertype != rhs.ordertype {return false} | |
| 954 | + if lhs.side != rhs.side {return false} | |
| 955 | + if lhs.price != rhs.price {return false} | |
| 956 | + if lhs.quantity != rhs.quantity {return false} | |
| 957 | + if lhs.timeinforce != rhs.timeinforce {return false} | |
| 958 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 959 | + return true | |
| 960 | + } | |
| 961 | +} | |
| 962 | + | |
| 963 | +extension TW_Binance_Proto_CancelTradeOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 964 | + public static let protoMessageName: String = _protobuf_package + ".CancelTradeOrder" | |
| 965 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 966 | + 1: .same(proto: "sender"), | |
| 967 | + 2: .same(proto: "symbol"), | |
| 968 | + 3: .same(proto: "refid"), | |
| 969 | + ] | |
| 970 | + | |
| 971 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 972 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 973 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 974 | + // allocates stack space for every case branch when no optimizations are | |
| 975 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 976 | + switch fieldNumber { | |
| 977 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.sender) }() | |
| 978 | + case 2: try { try decoder.decodeSingularStringField(value: &self.symbol) }() | |
| 979 | + case 3: try { try decoder.decodeSingularStringField(value: &self.refid) }() | |
| 980 | + default: break | |
| 981 | + } | |
| 982 | + } | |
| 983 | + } | |
| 984 | + | |
| 985 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 986 | + if !self.sender.isEmpty { | |
| 987 | + try visitor.visitSingularBytesField(value: self.sender, fieldNumber: 1) | |
| 988 | + } | |
| 989 | + if !self.symbol.isEmpty { | |
| 990 | + try visitor.visitSingularStringField(value: self.symbol, fieldNumber: 2) | |
| 991 | + } | |
| 992 | + if !self.refid.isEmpty { | |
| 993 | + try visitor.visitSingularStringField(value: self.refid, fieldNumber: 3) | |
| 994 | + } | |
| 995 | + try unknownFields.traverse(visitor: &visitor) | |
| 996 | + } | |
| 997 | + | |
| 998 | + public static func ==(lhs: TW_Binance_Proto_CancelTradeOrder, rhs: TW_Binance_Proto_CancelTradeOrder) -> Bool { | |
| 999 | + if lhs.sender != rhs.sender {return false} | |
| 1000 | + if lhs.symbol != rhs.symbol {return false} | |
| 1001 | + if lhs.refid != rhs.refid {return false} | |
| 1002 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1003 | + return true | |
| 1004 | + } | |
| 1005 | +} | |
| 1006 | + | |
| 1007 | +extension TW_Binance_Proto_SendOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1008 | + public static let protoMessageName: String = _protobuf_package + ".SendOrder" | |
| 1009 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1010 | + 1: .same(proto: "inputs"), | |
| 1011 | + 2: .same(proto: "outputs"), | |
| 1012 | + ] | |
| 1013 | + | |
| 1014 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1015 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1016 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1017 | + // allocates stack space for every case branch when no optimizations are | |
| 1018 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1019 | + switch fieldNumber { | |
| 1020 | + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.inputs) }() | |
| 1021 | + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.outputs) }() | |
| 1022 | + default: break | |
| 1023 | + } | |
| 1024 | + } | |
| 1025 | + } | |
| 1026 | + | |
| 1027 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1028 | + if !self.inputs.isEmpty { | |
| 1029 | + try visitor.visitRepeatedMessageField(value: self.inputs, fieldNumber: 1) | |
| 1030 | + } | |
| 1031 | + if !self.outputs.isEmpty { | |
| 1032 | + try visitor.visitRepeatedMessageField(value: self.outputs, fieldNumber: 2) | |
| 1033 | + } | |
| 1034 | + try unknownFields.traverse(visitor: &visitor) | |
| 1035 | + } | |
| 1036 | + | |
| 1037 | + public static func ==(lhs: TW_Binance_Proto_SendOrder, rhs: TW_Binance_Proto_SendOrder) -> Bool { | |
| 1038 | + if lhs.inputs != rhs.inputs {return false} | |
| 1039 | + if lhs.outputs != rhs.outputs {return false} | |
| 1040 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1041 | + return true | |
| 1042 | + } | |
| 1043 | +} | |
| 1044 | + | |
| 1045 | +extension TW_Binance_Proto_SendOrder.Token: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1046 | + public static let protoMessageName: String = TW_Binance_Proto_SendOrder.protoMessageName + ".Token" | |
| 1047 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1048 | + 1: .same(proto: "denom"), | |
| 1049 | + 2: .same(proto: "amount"), | |
| 1050 | + ] | |
| 1051 | + | |
| 1052 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1053 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1054 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1055 | + // allocates stack space for every case branch when no optimizations are | |
| 1056 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1057 | + switch fieldNumber { | |
| 1058 | + case 1: try { try decoder.decodeSingularStringField(value: &self.denom) }() | |
| 1059 | + case 2: try { try decoder.decodeSingularInt64Field(value: &self.amount) }() | |
| 1060 | + default: break | |
| 1061 | + } | |
| 1062 | + } | |
| 1063 | + } | |
| 1064 | + | |
| 1065 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1066 | + if !self.denom.isEmpty { | |
| 1067 | + try visitor.visitSingularStringField(value: self.denom, fieldNumber: 1) | |
| 1068 | + } | |
| 1069 | + if self.amount != 0 { | |
| 1070 | + try visitor.visitSingularInt64Field(value: self.amount, fieldNumber: 2) | |
| 1071 | + } | |
| 1072 | + try unknownFields.traverse(visitor: &visitor) | |
| 1073 | + } | |
| 1074 | + | |
| 1075 | + public static func ==(lhs: TW_Binance_Proto_SendOrder.Token, rhs: TW_Binance_Proto_SendOrder.Token) -> Bool { | |
| 1076 | + if lhs.denom != rhs.denom {return false} | |
| 1077 | + if lhs.amount != rhs.amount {return false} | |
| 1078 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1079 | + return true | |
| 1080 | + } | |
| 1081 | +} | |
| 1082 | + | |
| 1083 | +extension TW_Binance_Proto_SendOrder.Input: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1084 | + public static let protoMessageName: String = TW_Binance_Proto_SendOrder.protoMessageName + ".Input" | |
| 1085 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1086 | + 1: .same(proto: "address"), | |
| 1087 | + 2: .same(proto: "coins"), | |
| 1088 | + ] | |
| 1089 | + | |
| 1090 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1091 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1092 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1093 | + // allocates stack space for every case branch when no optimizations are | |
| 1094 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1095 | + switch fieldNumber { | |
| 1096 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.address) }() | |
| 1097 | + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.coins) }() | |
| 1098 | + default: break | |
| 1099 | + } | |
| 1100 | + } | |
| 1101 | + } | |
| 1102 | + | |
| 1103 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1104 | + if !self.address.isEmpty { | |
| 1105 | + try visitor.visitSingularBytesField(value: self.address, fieldNumber: 1) | |
| 1106 | + } | |
| 1107 | + if !self.coins.isEmpty { | |
| 1108 | + try visitor.visitRepeatedMessageField(value: self.coins, fieldNumber: 2) | |
| 1109 | + } | |
| 1110 | + try unknownFields.traverse(visitor: &visitor) | |
| 1111 | + } | |
| 1112 | + | |
| 1113 | + public static func ==(lhs: TW_Binance_Proto_SendOrder.Input, rhs: TW_Binance_Proto_SendOrder.Input) -> Bool { | |
| 1114 | + if lhs.address != rhs.address {return false} | |
| 1115 | + if lhs.coins != rhs.coins {return false} | |
| 1116 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1117 | + return true | |
| 1118 | + } | |
| 1119 | +} | |
| 1120 | + | |
| 1121 | +extension TW_Binance_Proto_SendOrder.Output: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1122 | + public static let protoMessageName: String = TW_Binance_Proto_SendOrder.protoMessageName + ".Output" | |
| 1123 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1124 | + 1: .same(proto: "address"), | |
| 1125 | + 2: .same(proto: "coins"), | |
| 1126 | + ] | |
| 1127 | + | |
| 1128 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1129 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1130 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1131 | + // allocates stack space for every case branch when no optimizations are | |
| 1132 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1133 | + switch fieldNumber { | |
| 1134 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.address) }() | |
| 1135 | + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.coins) }() | |
| 1136 | + default: break | |
| 1137 | + } | |
| 1138 | + } | |
| 1139 | + } | |
| 1140 | + | |
| 1141 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1142 | + if !self.address.isEmpty { | |
| 1143 | + try visitor.visitSingularBytesField(value: self.address, fieldNumber: 1) | |
| 1144 | + } | |
| 1145 | + if !self.coins.isEmpty { | |
| 1146 | + try visitor.visitRepeatedMessageField(value: self.coins, fieldNumber: 2) | |
| 1147 | + } | |
| 1148 | + try unknownFields.traverse(visitor: &visitor) | |
| 1149 | + } | |
| 1150 | + | |
| 1151 | + public static func ==(lhs: TW_Binance_Proto_SendOrder.Output, rhs: TW_Binance_Proto_SendOrder.Output) -> Bool { | |
| 1152 | + if lhs.address != rhs.address {return false} | |
| 1153 | + if lhs.coins != rhs.coins {return false} | |
| 1154 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1155 | + return true | |
| 1156 | + } | |
| 1157 | +} | |
| 1158 | + | |
| 1159 | +extension TW_Binance_Proto_HTLTOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1160 | + public static let protoMessageName: String = _protobuf_package + ".HTLTOrder" | |
| 1161 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1162 | + 1: .same(proto: "from"), | |
| 1163 | + 2: .same(proto: "to"), | |
| 1164 | + 3: .standard(proto: "recipient_other_chain"), | |
| 1165 | + 4: .standard(proto: "sender_other_chain"), | |
| 1166 | + 5: .standard(proto: "random_number_hash"), | |
| 1167 | + 6: .same(proto: "timestamp"), | |
| 1168 | + 7: .same(proto: "amount"), | |
| 1169 | + 8: .standard(proto: "expected_income"), | |
| 1170 | + 9: .standard(proto: "height_span"), | |
| 1171 | + 10: .standard(proto: "cross_chain"), | |
| 1172 | + ] | |
| 1173 | + | |
| 1174 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1175 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1176 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1177 | + // allocates stack space for every case branch when no optimizations are | |
| 1178 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1179 | + switch fieldNumber { | |
| 1180 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.from) }() | |
| 1181 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.to) }() | |
| 1182 | + case 3: try { try decoder.decodeSingularStringField(value: &self.recipientOtherChain) }() | |
| 1183 | + case 4: try { try decoder.decodeSingularStringField(value: &self.senderOtherChain) }() | |
| 1184 | + case 5: try { try decoder.decodeSingularBytesField(value: &self.randomNumberHash) }() | |
| 1185 | + case 6: try { try decoder.decodeSingularInt64Field(value: &self.timestamp) }() | |
| 1186 | + case 7: try { try decoder.decodeRepeatedMessageField(value: &self.amount) }() | |
| 1187 | + case 8: try { try decoder.decodeSingularStringField(value: &self.expectedIncome) }() | |
| 1188 | + case 9: try { try decoder.decodeSingularInt64Field(value: &self.heightSpan) }() | |
| 1189 | + case 10: try { try decoder.decodeSingularBoolField(value: &self.crossChain) }() | |
| 1190 | + default: break | |
| 1191 | + } | |
| 1192 | + } | |
| 1193 | + } | |
| 1194 | + | |
| 1195 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1196 | + if !self.from.isEmpty { | |
| 1197 | + try visitor.visitSingularBytesField(value: self.from, fieldNumber: 1) | |
| 1198 | + } | |
| 1199 | + if !self.to.isEmpty { | |
| 1200 | + try visitor.visitSingularBytesField(value: self.to, fieldNumber: 2) | |
| 1201 | + } | |
| 1202 | + if !self.recipientOtherChain.isEmpty { | |
| 1203 | + try visitor.visitSingularStringField(value: self.recipientOtherChain, fieldNumber: 3) | |
| 1204 | + } | |
| 1205 | + if !self.senderOtherChain.isEmpty { | |
| 1206 | + try visitor.visitSingularStringField(value: self.senderOtherChain, fieldNumber: 4) | |
| 1207 | + } | |
| 1208 | + if !self.randomNumberHash.isEmpty { | |
| 1209 | + try visitor.visitSingularBytesField(value: self.randomNumberHash, fieldNumber: 5) | |
| 1210 | + } | |
| 1211 | + if self.timestamp != 0 { | |
| 1212 | + try visitor.visitSingularInt64Field(value: self.timestamp, fieldNumber: 6) | |
| 1213 | + } | |
| 1214 | + if !self.amount.isEmpty { | |
| 1215 | + try visitor.visitRepeatedMessageField(value: self.amount, fieldNumber: 7) | |
| 1216 | + } | |
| 1217 | + if !self.expectedIncome.isEmpty { | |
| 1218 | + try visitor.visitSingularStringField(value: self.expectedIncome, fieldNumber: 8) | |
| 1219 | + } | |
| 1220 | + if self.heightSpan != 0 { | |
| 1221 | + try visitor.visitSingularInt64Field(value: self.heightSpan, fieldNumber: 9) | |
| 1222 | + } | |
| 1223 | + if self.crossChain != false { | |
| 1224 | + try visitor.visitSingularBoolField(value: self.crossChain, fieldNumber: 10) | |
| 1225 | + } | |
| 1226 | + try unknownFields.traverse(visitor: &visitor) | |
| 1227 | + } | |
| 1228 | + | |
| 1229 | + public static func ==(lhs: TW_Binance_Proto_HTLTOrder, rhs: TW_Binance_Proto_HTLTOrder) -> Bool { | |
| 1230 | + if lhs.from != rhs.from {return false} | |
| 1231 | + if lhs.to != rhs.to {return false} | |
| 1232 | + if lhs.recipientOtherChain != rhs.recipientOtherChain {return false} | |
| 1233 | + if lhs.senderOtherChain != rhs.senderOtherChain {return false} | |
| 1234 | + if lhs.randomNumberHash != rhs.randomNumberHash {return false} | |
| 1235 | + if lhs.timestamp != rhs.timestamp {return false} | |
| 1236 | + if lhs.amount != rhs.amount {return false} | |
| 1237 | + if lhs.expectedIncome != rhs.expectedIncome {return false} | |
| 1238 | + if lhs.heightSpan != rhs.heightSpan {return false} | |
| 1239 | + if lhs.crossChain != rhs.crossChain {return false} | |
| 1240 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1241 | + return true | |
| 1242 | + } | |
| 1243 | +} | |
| 1244 | + | |
| 1245 | +extension TW_Binance_Proto_DepositHTLTOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1246 | + public static let protoMessageName: String = _protobuf_package + ".DepositHTLTOrder" | |
| 1247 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1248 | + 1: .same(proto: "from"), | |
| 1249 | + 2: .same(proto: "amount"), | |
| 1250 | + 3: .standard(proto: "swap_id"), | |
| 1251 | + ] | |
| 1252 | + | |
| 1253 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1254 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1255 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1256 | + // allocates stack space for every case branch when no optimizations are | |
| 1257 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1258 | + switch fieldNumber { | |
| 1259 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.from) }() | |
| 1260 | + case 2: try { try decoder.decodeRepeatedMessageField(value: &self.amount) }() | |
| 1261 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.swapID) }() | |
| 1262 | + default: break | |
| 1263 | + } | |
| 1264 | + } | |
| 1265 | + } | |
| 1266 | + | |
| 1267 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1268 | + if !self.from.isEmpty { | |
| 1269 | + try visitor.visitSingularBytesField(value: self.from, fieldNumber: 1) | |
| 1270 | + } | |
| 1271 | + if !self.amount.isEmpty { | |
| 1272 | + try visitor.visitRepeatedMessageField(value: self.amount, fieldNumber: 2) | |
| 1273 | + } | |
| 1274 | + if !self.swapID.isEmpty { | |
| 1275 | + try visitor.visitSingularBytesField(value: self.swapID, fieldNumber: 3) | |
| 1276 | + } | |
| 1277 | + try unknownFields.traverse(visitor: &visitor) | |
| 1278 | + } | |
| 1279 | + | |
| 1280 | + public static func ==(lhs: TW_Binance_Proto_DepositHTLTOrder, rhs: TW_Binance_Proto_DepositHTLTOrder) -> Bool { | |
| 1281 | + if lhs.from != rhs.from {return false} | |
| 1282 | + if lhs.amount != rhs.amount {return false} | |
| 1283 | + if lhs.swapID != rhs.swapID {return false} | |
| 1284 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1285 | + return true | |
| 1286 | + } | |
| 1287 | +} | |
| 1288 | + | |
| 1289 | +extension TW_Binance_Proto_ClaimHTLOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1290 | + public static let protoMessageName: String = _protobuf_package + ".ClaimHTLOrder" | |
| 1291 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1292 | + 1: .same(proto: "from"), | |
| 1293 | + 2: .standard(proto: "swap_id"), | |
| 1294 | + 3: .standard(proto: "random_number"), | |
| 1295 | + ] | |
| 1296 | + | |
| 1297 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1298 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1299 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1300 | + // allocates stack space for every case branch when no optimizations are | |
| 1301 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1302 | + switch fieldNumber { | |
| 1303 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.from) }() | |
| 1304 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.swapID) }() | |
| 1305 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.randomNumber) }() | |
| 1306 | + default: break | |
| 1307 | + } | |
| 1308 | + } | |
| 1309 | + } | |
| 1310 | + | |
| 1311 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1312 | + if !self.from.isEmpty { | |
| 1313 | + try visitor.visitSingularBytesField(value: self.from, fieldNumber: 1) | |
| 1314 | + } | |
| 1315 | + if !self.swapID.isEmpty { | |
| 1316 | + try visitor.visitSingularBytesField(value: self.swapID, fieldNumber: 2) | |
| 1317 | + } | |
| 1318 | + if !self.randomNumber.isEmpty { | |
| 1319 | + try visitor.visitSingularBytesField(value: self.randomNumber, fieldNumber: 3) | |
| 1320 | + } | |
| 1321 | + try unknownFields.traverse(visitor: &visitor) | |
| 1322 | + } | |
| 1323 | + | |
| 1324 | + public static func ==(lhs: TW_Binance_Proto_ClaimHTLOrder, rhs: TW_Binance_Proto_ClaimHTLOrder) -> Bool { | |
| 1325 | + if lhs.from != rhs.from {return false} | |
| 1326 | + if lhs.swapID != rhs.swapID {return false} | |
| 1327 | + if lhs.randomNumber != rhs.randomNumber {return false} | |
| 1328 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1329 | + return true | |
| 1330 | + } | |
| 1331 | +} | |
| 1332 | + | |
| 1333 | +extension TW_Binance_Proto_RefundHTLTOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1334 | + public static let protoMessageName: String = _protobuf_package + ".RefundHTLTOrder" | |
| 1335 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1336 | + 1: .same(proto: "from"), | |
| 1337 | + 2: .standard(proto: "swap_id"), | |
| 1338 | + ] | |
| 1339 | + | |
| 1340 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1341 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1342 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1343 | + // allocates stack space for every case branch when no optimizations are | |
| 1344 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1345 | + switch fieldNumber { | |
| 1346 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.from) }() | |
| 1347 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.swapID) }() | |
| 1348 | + default: break | |
| 1349 | + } | |
| 1350 | + } | |
| 1351 | + } | |
| 1352 | + | |
| 1353 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1354 | + if !self.from.isEmpty { | |
| 1355 | + try visitor.visitSingularBytesField(value: self.from, fieldNumber: 1) | |
| 1356 | + } | |
| 1357 | + if !self.swapID.isEmpty { | |
| 1358 | + try visitor.visitSingularBytesField(value: self.swapID, fieldNumber: 2) | |
| 1359 | + } | |
| 1360 | + try unknownFields.traverse(visitor: &visitor) | |
| 1361 | + } | |
| 1362 | + | |
| 1363 | + public static func ==(lhs: TW_Binance_Proto_RefundHTLTOrder, rhs: TW_Binance_Proto_RefundHTLTOrder) -> Bool { | |
| 1364 | + if lhs.from != rhs.from {return false} | |
| 1365 | + if lhs.swapID != rhs.swapID {return false} | |
| 1366 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1367 | + return true | |
| 1368 | + } | |
| 1369 | +} | |
| 1370 | + | |
| 1371 | +extension TW_Binance_Proto_TransferOut: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1372 | + public static let protoMessageName: String = _protobuf_package + ".TransferOut" | |
| 1373 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1374 | + 1: .same(proto: "from"), | |
| 1375 | + 2: .same(proto: "to"), | |
| 1376 | + 3: .same(proto: "amount"), | |
| 1377 | + 4: .standard(proto: "expire_time"), | |
| 1378 | + ] | |
| 1379 | + | |
| 1380 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1381 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1382 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1383 | + // allocates stack space for every case branch when no optimizations are | |
| 1384 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1385 | + switch fieldNumber { | |
| 1386 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.from) }() | |
| 1387 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.to) }() | |
| 1388 | + case 3: try { try decoder.decodeSingularMessageField(value: &self._amount) }() | |
| 1389 | + case 4: try { try decoder.decodeSingularInt64Field(value: &self.expireTime) }() | |
| 1390 | + default: break | |
| 1391 | + } | |
| 1392 | + } | |
| 1393 | + } | |
| 1394 | + | |
| 1395 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1396 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1397 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1398 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1399 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1400 | + if !self.from.isEmpty { | |
| 1401 | + try visitor.visitSingularBytesField(value: self.from, fieldNumber: 1) | |
| 1402 | + } | |
| 1403 | + if !self.to.isEmpty { | |
| 1404 | + try visitor.visitSingularBytesField(value: self.to, fieldNumber: 2) | |
| 1405 | + } | |
| 1406 | + try { if let v = self._amount { | |
| 1407 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) | |
| 1408 | + } }() | |
| 1409 | + if self.expireTime != 0 { | |
| 1410 | + try visitor.visitSingularInt64Field(value: self.expireTime, fieldNumber: 4) | |
| 1411 | + } | |
| 1412 | + try unknownFields.traverse(visitor: &visitor) | |
| 1413 | + } | |
| 1414 | + | |
| 1415 | + public static func ==(lhs: TW_Binance_Proto_TransferOut, rhs: TW_Binance_Proto_TransferOut) -> Bool { | |
| 1416 | + if lhs.from != rhs.from {return false} | |
| 1417 | + if lhs.to != rhs.to {return false} | |
| 1418 | + if lhs._amount != rhs._amount {return false} | |
| 1419 | + if lhs.expireTime != rhs.expireTime {return false} | |
| 1420 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1421 | + return true | |
| 1422 | + } | |
| 1423 | +} | |
| 1424 | + | |
| 1425 | +extension TW_Binance_Proto_SideChainDelegate: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1426 | + public static let protoMessageName: String = _protobuf_package + ".SideChainDelegate" | |
| 1427 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1428 | + 1: .standard(proto: "delegator_addr"), | |
| 1429 | + 2: .standard(proto: "validator_addr"), | |
| 1430 | + 3: .same(proto: "delegation"), | |
| 1431 | + 4: .standard(proto: "chain_id"), | |
| 1432 | + ] | |
| 1433 | + | |
| 1434 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1435 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1436 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1437 | + // allocates stack space for every case branch when no optimizations are | |
| 1438 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1439 | + switch fieldNumber { | |
| 1440 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.delegatorAddr) }() | |
| 1441 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.validatorAddr) }() | |
| 1442 | + case 3: try { try decoder.decodeSingularMessageField(value: &self._delegation) }() | |
| 1443 | + case 4: try { try decoder.decodeSingularStringField(value: &self.chainID) }() | |
| 1444 | + default: break | |
| 1445 | + } | |
| 1446 | + } | |
| 1447 | + } | |
| 1448 | + | |
| 1449 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1450 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1451 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1452 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1453 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1454 | + if !self.delegatorAddr.isEmpty { | |
| 1455 | + try visitor.visitSingularBytesField(value: self.delegatorAddr, fieldNumber: 1) | |
| 1456 | + } | |
| 1457 | + if !self.validatorAddr.isEmpty { | |
| 1458 | + try visitor.visitSingularBytesField(value: self.validatorAddr, fieldNumber: 2) | |
| 1459 | + } | |
| 1460 | + try { if let v = self._delegation { | |
| 1461 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) | |
| 1462 | + } }() | |
| 1463 | + if !self.chainID.isEmpty { | |
| 1464 | + try visitor.visitSingularStringField(value: self.chainID, fieldNumber: 4) | |
| 1465 | + } | |
| 1466 | + try unknownFields.traverse(visitor: &visitor) | |
| 1467 | + } | |
| 1468 | + | |
| 1469 | + public static func ==(lhs: TW_Binance_Proto_SideChainDelegate, rhs: TW_Binance_Proto_SideChainDelegate) -> Bool { | |
| 1470 | + if lhs.delegatorAddr != rhs.delegatorAddr {return false} | |
| 1471 | + if lhs.validatorAddr != rhs.validatorAddr {return false} | |
| 1472 | + if lhs._delegation != rhs._delegation {return false} | |
| 1473 | + if lhs.chainID != rhs.chainID {return false} | |
| 1474 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1475 | + return true | |
| 1476 | + } | |
| 1477 | +} | |
| 1478 | + | |
| 1479 | +extension TW_Binance_Proto_SideChainRedelegate: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1480 | + public static let protoMessageName: String = _protobuf_package + ".SideChainRedelegate" | |
| 1481 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1482 | + 1: .standard(proto: "delegator_addr"), | |
| 1483 | + 2: .standard(proto: "validator_src_addr"), | |
| 1484 | + 3: .standard(proto: "validator_dst_addr"), | |
| 1485 | + 4: .same(proto: "amount"), | |
| 1486 | + 5: .standard(proto: "chain_id"), | |
| 1487 | + ] | |
| 1488 | + | |
| 1489 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1490 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1491 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1492 | + // allocates stack space for every case branch when no optimizations are | |
| 1493 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1494 | + switch fieldNumber { | |
| 1495 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.delegatorAddr) }() | |
| 1496 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.validatorSrcAddr) }() | |
| 1497 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.validatorDstAddr) }() | |
| 1498 | + case 4: try { try decoder.decodeSingularMessageField(value: &self._amount) }() | |
| 1499 | + case 5: try { try decoder.decodeSingularStringField(value: &self.chainID) }() | |
| 1500 | + default: break | |
| 1501 | + } | |
| 1502 | + } | |
| 1503 | + } | |
| 1504 | + | |
| 1505 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1506 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1507 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1508 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1509 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1510 | + if !self.delegatorAddr.isEmpty { | |
| 1511 | + try visitor.visitSingularBytesField(value: self.delegatorAddr, fieldNumber: 1) | |
| 1512 | + } | |
| 1513 | + if !self.validatorSrcAddr.isEmpty { | |
| 1514 | + try visitor.visitSingularBytesField(value: self.validatorSrcAddr, fieldNumber: 2) | |
| 1515 | + } | |
| 1516 | + if !self.validatorDstAddr.isEmpty { | |
| 1517 | + try visitor.visitSingularBytesField(value: self.validatorDstAddr, fieldNumber: 3) | |
| 1518 | + } | |
| 1519 | + try { if let v = self._amount { | |
| 1520 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) | |
| 1521 | + } }() | |
| 1522 | + if !self.chainID.isEmpty { | |
| 1523 | + try visitor.visitSingularStringField(value: self.chainID, fieldNumber: 5) | |
| 1524 | + } | |
| 1525 | + try unknownFields.traverse(visitor: &visitor) | |
| 1526 | + } | |
| 1527 | + | |
| 1528 | + public static func ==(lhs: TW_Binance_Proto_SideChainRedelegate, rhs: TW_Binance_Proto_SideChainRedelegate) -> Bool { | |
| 1529 | + if lhs.delegatorAddr != rhs.delegatorAddr {return false} | |
| 1530 | + if lhs.validatorSrcAddr != rhs.validatorSrcAddr {return false} | |
| 1531 | + if lhs.validatorDstAddr != rhs.validatorDstAddr {return false} | |
| 1532 | + if lhs._amount != rhs._amount {return false} | |
| 1533 | + if lhs.chainID != rhs.chainID {return false} | |
| 1534 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1535 | + return true | |
| 1536 | + } | |
| 1537 | +} | |
| 1538 | + | |
| 1539 | +extension TW_Binance_Proto_SideChainUndelegate: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1540 | + public static let protoMessageName: String = _protobuf_package + ".SideChainUndelegate" | |
| 1541 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1542 | + 1: .standard(proto: "delegator_addr"), | |
| 1543 | + 2: .standard(proto: "validator_addr"), | |
| 1544 | + 3: .same(proto: "amount"), | |
| 1545 | + 4: .standard(proto: "chain_id"), | |
| 1546 | + ] | |
| 1547 | + | |
| 1548 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1549 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1550 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1551 | + // allocates stack space for every case branch when no optimizations are | |
| 1552 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1553 | + switch fieldNumber { | |
| 1554 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.delegatorAddr) }() | |
| 1555 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.validatorAddr) }() | |
| 1556 | + case 3: try { try decoder.decodeSingularMessageField(value: &self._amount) }() | |
| 1557 | + case 4: try { try decoder.decodeSingularStringField(value: &self.chainID) }() | |
| 1558 | + default: break | |
| 1559 | + } | |
| 1560 | + } | |
| 1561 | + } | |
| 1562 | + | |
| 1563 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1564 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1565 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1566 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1567 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1568 | + if !self.delegatorAddr.isEmpty { | |
| 1569 | + try visitor.visitSingularBytesField(value: self.delegatorAddr, fieldNumber: 1) | |
| 1570 | + } | |
| 1571 | + if !self.validatorAddr.isEmpty { | |
| 1572 | + try visitor.visitSingularBytesField(value: self.validatorAddr, fieldNumber: 2) | |
| 1573 | + } | |
| 1574 | + try { if let v = self._amount { | |
| 1575 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 3) | |
| 1576 | + } }() | |
| 1577 | + if !self.chainID.isEmpty { | |
| 1578 | + try visitor.visitSingularStringField(value: self.chainID, fieldNumber: 4) | |
| 1579 | + } | |
| 1580 | + try unknownFields.traverse(visitor: &visitor) | |
| 1581 | + } | |
| 1582 | + | |
| 1583 | + public static func ==(lhs: TW_Binance_Proto_SideChainUndelegate, rhs: TW_Binance_Proto_SideChainUndelegate) -> Bool { | |
| 1584 | + if lhs.delegatorAddr != rhs.delegatorAddr {return false} | |
| 1585 | + if lhs.validatorAddr != rhs.validatorAddr {return false} | |
| 1586 | + if lhs._amount != rhs._amount {return false} | |
| 1587 | + if lhs.chainID != rhs.chainID {return false} | |
| 1588 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1589 | + return true | |
| 1590 | + } | |
| 1591 | +} | |
| 1592 | + | |
| 1593 | +extension TW_Binance_Proto_SideChainStakeMigration: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1594 | + public static let protoMessageName: String = _protobuf_package + ".SideChainStakeMigration" | |
| 1595 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1596 | + 1: .standard(proto: "validator_src_addr"), | |
| 1597 | + 2: .standard(proto: "validator_dst_addr"), | |
| 1598 | + 3: .standard(proto: "delegator_addr"), | |
| 1599 | + 4: .standard(proto: "refund_addr"), | |
| 1600 | + 5: .same(proto: "amount"), | |
| 1601 | + ] | |
| 1602 | + | |
| 1603 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1604 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1605 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1606 | + // allocates stack space for every case branch when no optimizations are | |
| 1607 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1608 | + switch fieldNumber { | |
| 1609 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.validatorSrcAddr) }() | |
| 1610 | + case 2: try { try decoder.decodeSingularBytesField(value: &self.validatorDstAddr) }() | |
| 1611 | + case 3: try { try decoder.decodeSingularBytesField(value: &self.delegatorAddr) }() | |
| 1612 | + case 4: try { try decoder.decodeSingularBytesField(value: &self.refundAddr) }() | |
| 1613 | + case 5: try { try decoder.decodeSingularMessageField(value: &self._amount) }() | |
| 1614 | + default: break | |
| 1615 | + } | |
| 1616 | + } | |
| 1617 | + } | |
| 1618 | + | |
| 1619 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1620 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1621 | + // allocates stack space for every if/case branch local when no optimizations | |
| 1622 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 1623 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 1624 | + if !self.validatorSrcAddr.isEmpty { | |
| 1625 | + try visitor.visitSingularBytesField(value: self.validatorSrcAddr, fieldNumber: 1) | |
| 1626 | + } | |
| 1627 | + if !self.validatorDstAddr.isEmpty { | |
| 1628 | + try visitor.visitSingularBytesField(value: self.validatorDstAddr, fieldNumber: 2) | |
| 1629 | + } | |
| 1630 | + if !self.delegatorAddr.isEmpty { | |
| 1631 | + try visitor.visitSingularBytesField(value: self.delegatorAddr, fieldNumber: 3) | |
| 1632 | + } | |
| 1633 | + if !self.refundAddr.isEmpty { | |
| 1634 | + try visitor.visitSingularBytesField(value: self.refundAddr, fieldNumber: 4) | |
| 1635 | + } | |
| 1636 | + try { if let v = self._amount { | |
| 1637 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 5) | |
| 1638 | + } }() | |
| 1639 | + try unknownFields.traverse(visitor: &visitor) | |
| 1640 | + } | |
| 1641 | + | |
| 1642 | + public static func ==(lhs: TW_Binance_Proto_SideChainStakeMigration, rhs: TW_Binance_Proto_SideChainStakeMigration) -> Bool { | |
| 1643 | + if lhs.validatorSrcAddr != rhs.validatorSrcAddr {return false} | |
| 1644 | + if lhs.validatorDstAddr != rhs.validatorDstAddr {return false} | |
| 1645 | + if lhs.delegatorAddr != rhs.delegatorAddr {return false} | |
| 1646 | + if lhs.refundAddr != rhs.refundAddr {return false} | |
| 1647 | + if lhs._amount != rhs._amount {return false} | |
| 1648 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1649 | + return true | |
| 1650 | + } | |
| 1651 | +} | |
| 1652 | + | |
| 1653 | +extension TW_Binance_Proto_TimeLockOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1654 | + public static let protoMessageName: String = _protobuf_package + ".TimeLockOrder" | |
| 1655 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1656 | + 1: .standard(proto: "from_address"), | |
| 1657 | + 2: .same(proto: "description"), | |
| 1658 | + 3: .same(proto: "amount"), | |
| 1659 | + 4: .standard(proto: "lock_time"), | |
| 1660 | + ] | |
| 1661 | + | |
| 1662 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1663 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1664 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1665 | + // allocates stack space for every case branch when no optimizations are | |
| 1666 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1667 | + switch fieldNumber { | |
| 1668 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.fromAddress) }() | |
| 1669 | + case 2: try { try decoder.decodeSingularStringField(value: &self.description_p) }() | |
| 1670 | + case 3: try { try decoder.decodeRepeatedMessageField(value: &self.amount) }() | |
| 1671 | + case 4: try { try decoder.decodeSingularInt64Field(value: &self.lockTime) }() | |
| 1672 | + default: break | |
| 1673 | + } | |
| 1674 | + } | |
| 1675 | + } | |
| 1676 | + | |
| 1677 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1678 | + if !self.fromAddress.isEmpty { | |
| 1679 | + try visitor.visitSingularBytesField(value: self.fromAddress, fieldNumber: 1) | |
| 1680 | + } | |
| 1681 | + if !self.description_p.isEmpty { | |
| 1682 | + try visitor.visitSingularStringField(value: self.description_p, fieldNumber: 2) | |
| 1683 | + } | |
| 1684 | + if !self.amount.isEmpty { | |
| 1685 | + try visitor.visitRepeatedMessageField(value: self.amount, fieldNumber: 3) | |
| 1686 | + } | |
| 1687 | + if self.lockTime != 0 { | |
| 1688 | + try visitor.visitSingularInt64Field(value: self.lockTime, fieldNumber: 4) | |
| 1689 | + } | |
| 1690 | + try unknownFields.traverse(visitor: &visitor) | |
| 1691 | + } | |
| 1692 | + | |
| 1693 | + public static func ==(lhs: TW_Binance_Proto_TimeLockOrder, rhs: TW_Binance_Proto_TimeLockOrder) -> Bool { | |
| 1694 | + if lhs.fromAddress != rhs.fromAddress {return false} | |
| 1695 | + if lhs.description_p != rhs.description_p {return false} | |
| 1696 | + if lhs.amount != rhs.amount {return false} | |
| 1697 | + if lhs.lockTime != rhs.lockTime {return false} | |
| 1698 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1699 | + return true | |
| 1700 | + } | |
| 1701 | +} | |
| 1702 | + | |
| 1703 | +extension TW_Binance_Proto_TimeRelockOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1704 | + public static let protoMessageName: String = _protobuf_package + ".TimeRelockOrder" | |
| 1705 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1706 | + 1: .standard(proto: "from_address"), | |
| 1707 | + 2: .same(proto: "id"), | |
| 1708 | + 3: .same(proto: "description"), | |
| 1709 | + 4: .same(proto: "amount"), | |
| 1710 | + 5: .standard(proto: "lock_time"), | |
| 1711 | + ] | |
| 1712 | + | |
| 1713 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1714 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1715 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1716 | + // allocates stack space for every case branch when no optimizations are | |
| 1717 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1718 | + switch fieldNumber { | |
| 1719 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.fromAddress) }() | |
| 1720 | + case 2: try { try decoder.decodeSingularInt64Field(value: &self.id) }() | |
| 1721 | + case 3: try { try decoder.decodeSingularStringField(value: &self.description_p) }() | |
| 1722 | + case 4: try { try decoder.decodeRepeatedMessageField(value: &self.amount) }() | |
| 1723 | + case 5: try { try decoder.decodeSingularInt64Field(value: &self.lockTime) }() | |
| 1724 | + default: break | |
| 1725 | + } | |
| 1726 | + } | |
| 1727 | + } | |
| 1728 | + | |
| 1729 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1730 | + if !self.fromAddress.isEmpty { | |
| 1731 | + try visitor.visitSingularBytesField(value: self.fromAddress, fieldNumber: 1) | |
| 1732 | + } | |
| 1733 | + if self.id != 0 { | |
| 1734 | + try visitor.visitSingularInt64Field(value: self.id, fieldNumber: 2) | |
| 1735 | + } | |
| 1736 | + if !self.description_p.isEmpty { | |
| 1737 | + try visitor.visitSingularStringField(value: self.description_p, fieldNumber: 3) | |
| 1738 | + } | |
| 1739 | + if !self.amount.isEmpty { | |
| 1740 | + try visitor.visitRepeatedMessageField(value: self.amount, fieldNumber: 4) | |
| 1741 | + } | |
| 1742 | + if self.lockTime != 0 { | |
| 1743 | + try visitor.visitSingularInt64Field(value: self.lockTime, fieldNumber: 5) | |
| 1744 | + } | |
| 1745 | + try unknownFields.traverse(visitor: &visitor) | |
| 1746 | + } | |
| 1747 | + | |
| 1748 | + public static func ==(lhs: TW_Binance_Proto_TimeRelockOrder, rhs: TW_Binance_Proto_TimeRelockOrder) -> Bool { | |
| 1749 | + if lhs.fromAddress != rhs.fromAddress {return false} | |
| 1750 | + if lhs.id != rhs.id {return false} | |
| 1751 | + if lhs.description_p != rhs.description_p {return false} | |
| 1752 | + if lhs.amount != rhs.amount {return false} | |
| 1753 | + if lhs.lockTime != rhs.lockTime {return false} | |
| 1754 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1755 | + return true | |
| 1756 | + } | |
| 1757 | +} | |
| 1758 | + | |
| 1759 | +extension TW_Binance_Proto_TimeUnlockOrder: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1760 | + public static let protoMessageName: String = _protobuf_package + ".TimeUnlockOrder" | |
| 1761 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1762 | + 1: .standard(proto: "from_address"), | |
| 1763 | + 2: .same(proto: "id"), | |
| 1764 | + ] | |
| 1765 | + | |
| 1766 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1767 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1768 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1769 | + // allocates stack space for every case branch when no optimizations are | |
| 1770 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1771 | + switch fieldNumber { | |
| 1772 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.fromAddress) }() | |
| 1773 | + case 2: try { try decoder.decodeSingularInt64Field(value: &self.id) }() | |
| 1774 | + default: break | |
| 1775 | + } | |
| 1776 | + } | |
| 1777 | + } | |
| 1778 | + | |
| 1779 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 1780 | + if !self.fromAddress.isEmpty { | |
| 1781 | + try visitor.visitSingularBytesField(value: self.fromAddress, fieldNumber: 1) | |
| 1782 | + } | |
| 1783 | + if self.id != 0 { | |
| 1784 | + try visitor.visitSingularInt64Field(value: self.id, fieldNumber: 2) | |
| 1785 | + } | |
| 1786 | + try unknownFields.traverse(visitor: &visitor) | |
| 1787 | + } | |
| 1788 | + | |
| 1789 | + public static func ==(lhs: TW_Binance_Proto_TimeUnlockOrder, rhs: TW_Binance_Proto_TimeUnlockOrder) -> Bool { | |
| 1790 | + if lhs.fromAddress != rhs.fromAddress {return false} | |
| 1791 | + if lhs.id != rhs.id {return false} | |
| 1792 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 1793 | + return true | |
| 1794 | + } | |
| 1795 | +} | |
| 1796 | + | |
| 1797 | +extension TW_Binance_Proto_SigningInput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 1798 | + public static let protoMessageName: String = _protobuf_package + ".SigningInput" | |
| 1799 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 1800 | + 1: .standard(proto: "chain_id"), | |
| 1801 | + 2: .standard(proto: "account_number"), | |
| 1802 | + 3: .same(proto: "sequence"), | |
| 1803 | + 4: .same(proto: "source"), | |
| 1804 | + 5: .same(proto: "memo"), | |
| 1805 | + 6: .standard(proto: "private_key"), | |
| 1806 | + 8: .standard(proto: "trade_order"), | |
| 1807 | + 9: .standard(proto: "cancel_trade_order"), | |
| 1808 | + 10: .standard(proto: "send_order"), | |
| 1809 | + 13: .standard(proto: "htlt_order"), | |
| 1810 | + 14: .standard(proto: "depositHTLT_order"), | |
| 1811 | + 15: .standard(proto: "claimHTLT_order"), | |
| 1812 | + 16: .standard(proto: "refundHTLT_order"), | |
| 1813 | + 20: .standard(proto: "transfer_out_order"), | |
| 1814 | + 21: .standard(proto: "side_delegate_order"), | |
| 1815 | + 22: .standard(proto: "side_redelegate_order"), | |
| 1816 | + 23: .standard(proto: "side_undelegate_order"), | |
| 1817 | + 24: .standard(proto: "time_lock_order"), | |
| 1818 | + 25: .standard(proto: "time_relock_order"), | |
| 1819 | + 26: .standard(proto: "time_unlock_order"), | |
| 1820 | + 27: .standard(proto: "side_stake_migration_order"), | |
| 1821 | + ] | |
| 1822 | + | |
| 1823 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 1824 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 1825 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 1826 | + // allocates stack space for every case branch when no optimizations are | |
| 1827 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 1828 | + switch fieldNumber { | |
| 1829 | + case 1: try { try decoder.decodeSingularStringField(value: &self.chainID) }() | |
| 1830 | + case 2: try { try decoder.decodeSingularInt64Field(value: &self.accountNumber) }() | |
| 1831 | + case 3: try { try decoder.decodeSingularInt64Field(value: &self.sequence) }() | |
| 1832 | + case 4: try { try decoder.decodeSingularInt64Field(value: &self.source) }() | |
| 1833 | + case 5: try { try decoder.decodeSingularStringField(value: &self.memo) }() | |
| 1834 | + case 6: try { try decoder.decodeSingularBytesField(value: &self.privateKey) }() | |
| 1835 | + case 8: try { | |
| 1836 | + var v: TW_Binance_Proto_TradeOrder? | |
| 1837 | + var hadOneofValue = false | |
| 1838 | + if let current = self.orderOneof { | |
| 1839 | + hadOneofValue = true | |
| 1840 | + if case .tradeOrder(let m) = current {v = m} | |
| 1841 | + } | |
| 1842 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1843 | + if let v = v { | |
| 1844 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1845 | + self.orderOneof = .tradeOrder(v) | |
| 1846 | + } | |
| 1847 | + }() | |
| 1848 | + case 9: try { | |
| 1849 | + var v: TW_Binance_Proto_CancelTradeOrder? | |
| 1850 | + var hadOneofValue = false | |
| 1851 | + if let current = self.orderOneof { | |
| 1852 | + hadOneofValue = true | |
| 1853 | + if case .cancelTradeOrder(let m) = current {v = m} | |
| 1854 | + } | |
| 1855 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1856 | + if let v = v { | |
| 1857 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1858 | + self.orderOneof = .cancelTradeOrder(v) | |
| 1859 | + } | |
| 1860 | + }() | |
| 1861 | + case 10: try { | |
| 1862 | + var v: TW_Binance_Proto_SendOrder? | |
| 1863 | + var hadOneofValue = false | |
| 1864 | + if let current = self.orderOneof { | |
| 1865 | + hadOneofValue = true | |
| 1866 | + if case .sendOrder(let m) = current {v = m} | |
| 1867 | + } | |
| 1868 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1869 | + if let v = v { | |
| 1870 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1871 | + self.orderOneof = .sendOrder(v) | |
| 1872 | + } | |
| 1873 | + }() | |
| 1874 | + case 13: try { | |
| 1875 | + var v: TW_Binance_Proto_HTLTOrder? | |
| 1876 | + var hadOneofValue = false | |
| 1877 | + if let current = self.orderOneof { | |
| 1878 | + hadOneofValue = true | |
| 1879 | + if case .htltOrder(let m) = current {v = m} | |
| 1880 | + } | |
| 1881 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1882 | + if let v = v { | |
| 1883 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1884 | + self.orderOneof = .htltOrder(v) | |
| 1885 | + } | |
| 1886 | + }() | |
| 1887 | + case 14: try { | |
| 1888 | + var v: TW_Binance_Proto_DepositHTLTOrder? | |
| 1889 | + var hadOneofValue = false | |
| 1890 | + if let current = self.orderOneof { | |
| 1891 | + hadOneofValue = true | |
| 1892 | + if case .depositHtltOrder(let m) = current {v = m} | |
| 1893 | + } | |
| 1894 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1895 | + if let v = v { | |
| 1896 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1897 | + self.orderOneof = .depositHtltOrder(v) | |
| 1898 | + } | |
| 1899 | + }() | |
| 1900 | + case 15: try { | |
| 1901 | + var v: TW_Binance_Proto_ClaimHTLOrder? | |
| 1902 | + var hadOneofValue = false | |
| 1903 | + if let current = self.orderOneof { | |
| 1904 | + hadOneofValue = true | |
| 1905 | + if case .claimHtltOrder(let m) = current {v = m} | |
| 1906 | + } | |
| 1907 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1908 | + if let v = v { | |
| 1909 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1910 | + self.orderOneof = .claimHtltOrder(v) | |
| 1911 | + } | |
| 1912 | + }() | |
| 1913 | + case 16: try { | |
| 1914 | + var v: TW_Binance_Proto_RefundHTLTOrder? | |
| 1915 | + var hadOneofValue = false | |
| 1916 | + if let current = self.orderOneof { | |
| 1917 | + hadOneofValue = true | |
| 1918 | + if case .refundHtltOrder(let m) = current {v = m} | |
| 1919 | + } | |
| 1920 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1921 | + if let v = v { | |
| 1922 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1923 | + self.orderOneof = .refundHtltOrder(v) | |
| 1924 | + } | |
| 1925 | + }() | |
| 1926 | + case 20: try { | |
| 1927 | + var v: TW_Binance_Proto_TransferOut? | |
| 1928 | + var hadOneofValue = false | |
| 1929 | + if let current = self.orderOneof { | |
| 1930 | + hadOneofValue = true | |
| 1931 | + if case .transferOutOrder(let m) = current {v = m} | |
| 1932 | + } | |
| 1933 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1934 | + if let v = v { | |
| 1935 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1936 | + self.orderOneof = .transferOutOrder(v) | |
| 1937 | + } | |
| 1938 | + }() | |
| 1939 | + case 21: try { | |
| 1940 | + var v: TW_Binance_Proto_SideChainDelegate? | |
| 1941 | + var hadOneofValue = false | |
| 1942 | + if let current = self.orderOneof { | |
| 1943 | + hadOneofValue = true | |
| 1944 | + if case .sideDelegateOrder(let m) = current {v = m} | |
| 1945 | + } | |
| 1946 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1947 | + if let v = v { | |
| 1948 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1949 | + self.orderOneof = .sideDelegateOrder(v) | |
| 1950 | + } | |
| 1951 | + }() | |
| 1952 | + case 22: try { | |
| 1953 | + var v: TW_Binance_Proto_SideChainRedelegate? | |
| 1954 | + var hadOneofValue = false | |
| 1955 | + if let current = self.orderOneof { | |
| 1956 | + hadOneofValue = true | |
| 1957 | + if case .sideRedelegateOrder(let m) = current {v = m} | |
| 1958 | + } | |
| 1959 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1960 | + if let v = v { | |
| 1961 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1962 | + self.orderOneof = .sideRedelegateOrder(v) | |
| 1963 | + } | |
| 1964 | + }() | |
| 1965 | + case 23: try { | |
| 1966 | + var v: TW_Binance_Proto_SideChainUndelegate? | |
| 1967 | + var hadOneofValue = false | |
| 1968 | + if let current = self.orderOneof { | |
| 1969 | + hadOneofValue = true | |
| 1970 | + if case .sideUndelegateOrder(let m) = current {v = m} | |
| 1971 | + } | |
| 1972 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1973 | + if let v = v { | |
| 1974 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1975 | + self.orderOneof = .sideUndelegateOrder(v) | |
| 1976 | + } | |
| 1977 | + }() | |
| 1978 | + case 24: try { | |
| 1979 | + var v: TW_Binance_Proto_TimeLockOrder? | |
| 1980 | + var hadOneofValue = false | |
| 1981 | + if let current = self.orderOneof { | |
| 1982 | + hadOneofValue = true | |
| 1983 | + if case .timeLockOrder(let m) = current {v = m} | |
| 1984 | + } | |
| 1985 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1986 | + if let v = v { | |
| 1987 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 1988 | + self.orderOneof = .timeLockOrder(v) | |
| 1989 | + } | |
| 1990 | + }() | |
| 1991 | + case 25: try { | |
| 1992 | + var v: TW_Binance_Proto_TimeRelockOrder? | |
| 1993 | + var hadOneofValue = false | |
| 1994 | + if let current = self.orderOneof { | |
| 1995 | + hadOneofValue = true | |
| 1996 | + if case .timeRelockOrder(let m) = current {v = m} | |
| 1997 | + } | |
| 1998 | + try decoder.decodeSingularMessageField(value: &v) | |
| 1999 | + if let v = v { | |
| 2000 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 2001 | + self.orderOneof = .timeRelockOrder(v) | |
| 2002 | + } | |
| 2003 | + }() | |
| 2004 | + case 26: try { | |
| 2005 | + var v: TW_Binance_Proto_TimeUnlockOrder? | |
| 2006 | + var hadOneofValue = false | |
| 2007 | + if let current = self.orderOneof { | |
| 2008 | + hadOneofValue = true | |
| 2009 | + if case .timeUnlockOrder(let m) = current {v = m} | |
| 2010 | + } | |
| 2011 | + try decoder.decodeSingularMessageField(value: &v) | |
| 2012 | + if let v = v { | |
| 2013 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 2014 | + self.orderOneof = .timeUnlockOrder(v) | |
| 2015 | + } | |
| 2016 | + }() | |
| 2017 | + case 27: try { | |
| 2018 | + var v: TW_Binance_Proto_SideChainStakeMigration? | |
| 2019 | + var hadOneofValue = false | |
| 2020 | + if let current = self.orderOneof { | |
| 2021 | + hadOneofValue = true | |
| 2022 | + if case .sideStakeMigrationOrder(let m) = current {v = m} | |
| 2023 | + } | |
| 2024 | + try decoder.decodeSingularMessageField(value: &v) | |
| 2025 | + if let v = v { | |
| 2026 | + if hadOneofValue {try decoder.handleConflictingOneOf()} | |
| 2027 | + self.orderOneof = .sideStakeMigrationOrder(v) | |
| 2028 | + } | |
| 2029 | + }() | |
| 2030 | + default: break | |
| 2031 | + } | |
| 2032 | + } | |
| 2033 | + } | |
| 2034 | + | |
| 2035 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 2036 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 2037 | + // allocates stack space for every if/case branch local when no optimizations | |
| 2038 | + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and | |
| 2039 | + // https://github.com/apple/swift-protobuf/issues/1182 | |
| 2040 | + if !self.chainID.isEmpty { | |
| 2041 | + try visitor.visitSingularStringField(value: self.chainID, fieldNumber: 1) | |
| 2042 | + } | |
| 2043 | + if self.accountNumber != 0 { | |
| 2044 | + try visitor.visitSingularInt64Field(value: self.accountNumber, fieldNumber: 2) | |
| 2045 | + } | |
| 2046 | + if self.sequence != 0 { | |
| 2047 | + try visitor.visitSingularInt64Field(value: self.sequence, fieldNumber: 3) | |
| 2048 | + } | |
| 2049 | + if self.source != 0 { | |
| 2050 | + try visitor.visitSingularInt64Field(value: self.source, fieldNumber: 4) | |
| 2051 | + } | |
| 2052 | + if !self.memo.isEmpty { | |
| 2053 | + try visitor.visitSingularStringField(value: self.memo, fieldNumber: 5) | |
| 2054 | + } | |
| 2055 | + if !self.privateKey.isEmpty { | |
| 2056 | + try visitor.visitSingularBytesField(value: self.privateKey, fieldNumber: 6) | |
| 2057 | + } | |
| 2058 | + switch self.orderOneof { | |
| 2059 | + case .tradeOrder?: try { | |
| 2060 | + guard case .tradeOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2061 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 8) | |
| 2062 | + }() | |
| 2063 | + case .cancelTradeOrder?: try { | |
| 2064 | + guard case .cancelTradeOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2065 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 9) | |
| 2066 | + }() | |
| 2067 | + case .sendOrder?: try { | |
| 2068 | + guard case .sendOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2069 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 10) | |
| 2070 | + }() | |
| 2071 | + case .htltOrder?: try { | |
| 2072 | + guard case .htltOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2073 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 13) | |
| 2074 | + }() | |
| 2075 | + case .depositHtltOrder?: try { | |
| 2076 | + guard case .depositHtltOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2077 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 14) | |
| 2078 | + }() | |
| 2079 | + case .claimHtltOrder?: try { | |
| 2080 | + guard case .claimHtltOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2081 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 15) | |
| 2082 | + }() | |
| 2083 | + case .refundHtltOrder?: try { | |
| 2084 | + guard case .refundHtltOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2085 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 16) | |
| 2086 | + }() | |
| 2087 | + case .transferOutOrder?: try { | |
| 2088 | + guard case .transferOutOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2089 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 20) | |
| 2090 | + }() | |
| 2091 | + case .sideDelegateOrder?: try { | |
| 2092 | + guard case .sideDelegateOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2093 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 21) | |
| 2094 | + }() | |
| 2095 | + case .sideRedelegateOrder?: try { | |
| 2096 | + guard case .sideRedelegateOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2097 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 22) | |
| 2098 | + }() | |
| 2099 | + case .sideUndelegateOrder?: try { | |
| 2100 | + guard case .sideUndelegateOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2101 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 23) | |
| 2102 | + }() | |
| 2103 | + case .timeLockOrder?: try { | |
| 2104 | + guard case .timeLockOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2105 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 24) | |
| 2106 | + }() | |
| 2107 | + case .timeRelockOrder?: try { | |
| 2108 | + guard case .timeRelockOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2109 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 25) | |
| 2110 | + }() | |
| 2111 | + case .timeUnlockOrder?: try { | |
| 2112 | + guard case .timeUnlockOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2113 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 26) | |
| 2114 | + }() | |
| 2115 | + case .sideStakeMigrationOrder?: try { | |
| 2116 | + guard case .sideStakeMigrationOrder(let v)? = self.orderOneof else { preconditionFailure() } | |
| 2117 | + try visitor.visitSingularMessageField(value: v, fieldNumber: 27) | |
| 2118 | + }() | |
| 2119 | + case nil: break | |
| 2120 | + } | |
| 2121 | + try unknownFields.traverse(visitor: &visitor) | |
| 2122 | + } | |
| 2123 | + | |
| 2124 | + public static func ==(lhs: TW_Binance_Proto_SigningInput, rhs: TW_Binance_Proto_SigningInput) -> Bool { | |
| 2125 | + if lhs.chainID != rhs.chainID {return false} | |
| 2126 | + if lhs.accountNumber != rhs.accountNumber {return false} | |
| 2127 | + if lhs.sequence != rhs.sequence {return false} | |
| 2128 | + if lhs.source != rhs.source {return false} | |
| 2129 | + if lhs.memo != rhs.memo {return false} | |
| 2130 | + if lhs.privateKey != rhs.privateKey {return false} | |
| 2131 | + if lhs.orderOneof != rhs.orderOneof {return false} | |
| 2132 | + if lhs.unknownFields != rhs.unknownFields {return false} | |
| 2133 | + return true | |
| 2134 | + } | |
| 2135 | +} | |
| 2136 | + | |
| 2137 | +extension TW_Binance_Proto_SigningOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { | |
| 2138 | + public static let protoMessageName: String = _protobuf_package + ".SigningOutput" | |
| 2139 | + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ | |
| 2140 | + 1: .same(proto: "encoded"), | |
| 2141 | + 2: .same(proto: "error"), | |
| 2142 | + 3: .standard(proto: "error_message"), | |
| 2143 | + 4: .same(proto: "signature"), | |
| 2144 | + 5: .standard(proto: "signature_json"), | |
| 2145 | + ] | |
| 2146 | + | |
| 2147 | + public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { | |
| 2148 | + while let fieldNumber = try decoder.nextFieldNumber() { | |
| 2149 | + // The use of inline closures is to circumvent an issue where the compiler | |
| 2150 | + // allocates stack space for every case branch when no optimizations are | |
| 2151 | + // enabled. https://github.com/apple/swift-protobuf/issues/1034 | |
| 2152 | + switch fieldNumber { | |
| 2153 | + case 1: try { try decoder.decodeSingularBytesField(value: &self.encoded) }() | |
| 2154 | + case 2: try { try decoder.decodeSingularEnumField(value: &self.error) }() | |
| 2155 | + case 3: try { try decoder.decodeSingularStringField(value: &self.errorMessage) }() | |
| 2156 | + case 4: try { try decoder.decodeSingularBytesField(value: &self.signature) }() | |
| 2157 | + case 5: try { try decoder.decodeSingularStringField(value: &self.signatureJson) }() | |
| 2158 | + default: break | |
| 2159 | + } | |
| 2160 | + } | |
| 2161 | + } | |
| 2162 | + | |
| 2163 | + public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { | |
| 2164 | + if !self.encoded.isEmpty { | |
| 2165 | + try visitor.visitSingularBytesField(value: self.encoded, fieldNumber: 1) | |
| 2166 | + } | |
| 2167 | + if self.error != .ok { | |
| 2168 | + try visitor.visitSingularEnumField(value: self.error, fieldNumber: 2) | |
| 2169 | + } | |
| 2170 | + if !self.errorMessage.isEmpty { | |
| 2171 | + try visitor.visitSingularStringField(value: self.errorMessage, fieldNumber: 3) | |
Diff truncated — file too large.