diff --git a/src/Angor.Avalonia.sln b/src/Angor.Avalonia.sln
index 99fd8e77..e191f7ae 100644
--- a/src/Angor.Avalonia.sln
+++ b/src/Angor.Avalonia.sln
@@ -22,6 +22,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Angor.UI.Model.Implementati
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{5B7EE527-242E-4C87-9BB7-AD4E05EABC4C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Angor.Wallet", "Angor\Avalonia\Angor.Wallet\Angor.Wallet.csproj", "{287F370D-D680-4BE5-8577-7A180BD0A0E3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -52,6 +54,10 @@ Global
{B84751C6-1B82-4DE8-9FBE-F0A67D981C43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B84751C6-1B82-4DE8-9FBE-F0A67D981C43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B84751C6-1B82-4DE8-9FBE-F0A67D981C43}.Release|Any CPU.Build.0 = Release|Any CPU
+ {287F370D-D680-4BE5-8577-7A180BD0A0E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {287F370D-D680-4BE5-8577-7A180BD0A0E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {287F370D-D680-4BE5-8577-7A180BD0A0E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {287F370D-D680-4BE5-8577-7A180BD0A0E3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -64,5 +70,6 @@ Global
{539B4D21-F2A9-46A6-84F1-9A51884A62E9} = {5B7EE527-242E-4C87-9BB7-AD4E05EABC4C}
{B84751C6-1B82-4DE8-9FBE-F0A67D981C43} = {5B7EE527-242E-4C87-9BB7-AD4E05EABC4C}
{700DF0C4-C965-4662-A91F-CD3BE043AC9E} = {5B7EE527-242E-4C87-9BB7-AD4E05EABC4C}
+ {287F370D-D680-4BE5-8577-7A180BD0A0E3} = {5B7EE527-242E-4C87-9BB7-AD4E05EABC4C}
EndGlobalSection
EndGlobal
diff --git a/src/Angor/Avalonia/Angor.Wallet/Angor.Wallet.csproj b/src/Angor/Avalonia/Angor.Wallet/Angor.Wallet.csproj
new file mode 100644
index 00000000..b66defdc
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Angor.Wallet.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net9.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/src/Angor/Avalonia/Angor.Wallet/Application/ITransactionWatcher.cs b/src/Angor/Avalonia/Angor.Wallet/Application/ITransactionWatcher.cs
new file mode 100644
index 00000000..cca5b2d2
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Application/ITransactionWatcher.cs
@@ -0,0 +1,8 @@
+using Angor.Wallet.Domain;
+
+namespace Angor.Wallet.Application;
+
+public interface ITransactionWatcher
+{
+ IObservable Watch(WalletId id);
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Application/IWalletAppService.cs b/src/Angor/Avalonia/Angor.Wallet/Application/IWalletAppService.cs
new file mode 100644
index 00000000..cf8a045a
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Application/IWalletAppService.cs
@@ -0,0 +1,15 @@
+using Angor.Wallet.Domain;
+using CSharpFunctionalExtensions;
+
+namespace Angor.Wallet.Application;
+
+public interface IWalletAppService
+{
+ Task> SendAmount(WalletId walletId, Amount amount, Address address, DomainFeeRate feeRate);
+ Task>> GetWallets();
+ Task>> GetTransactions(WalletId walletId);
+ Task> GetBalance(WalletId walletId);
+ Task> EstimateFee(WalletId walletId, Amount amount, Address address, DomainFeeRate feeRate);
+ Task> GetNextReceiveAddress(WalletId id);
+ Task> ImportWallet(string name, string seedwords, Maybe passphrase, string encryptionKey, BitcoinNetwork network);
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/Address.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/Address.cs
new file mode 100644
index 00000000..0105c13a
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/Address.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record Address(string Value);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/Amount.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/Amount.cs
new file mode 100644
index 00000000..4649ca41
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/Amount.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record Amount(long Value);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/Balance.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/Balance.cs
new file mode 100644
index 00000000..c5f0caab
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/Balance.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record Balance(long Value);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/BitcoinNetwork.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/BitcoinNetwork.cs
new file mode 100644
index 00000000..33321984
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/BitcoinNetwork.cs
@@ -0,0 +1,7 @@
+namespace Angor.Wallet.Domain;
+
+public enum BitcoinNetwork
+{
+ Mainnet,
+ Testnet
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/BroadcastedTransaction.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/BroadcastedTransaction.cs
new file mode 100644
index 00000000..2ab67297
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/BroadcastedTransaction.cs
@@ -0,0 +1,15 @@
+namespace Angor.Wallet.Domain;
+
+public record BroadcastedTransaction(
+ Balance Balance,
+ string Id,
+ IEnumerable WalletInputs,
+ IEnumerable WalletOutputs,
+ IEnumerable AllInputs,
+ IEnumerable AllOutputs,
+ long Fee,
+ bool IsConfirmed,
+ int? BlockHeight,
+ DateTimeOffset? BlockTime,
+ string RawJson
+);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/DerivationPath.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/DerivationPath.cs
new file mode 100644
index 00000000..2ab5e2b5
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/DerivationPath.cs
@@ -0,0 +1,20 @@
+namespace Angor.Wallet.Domain;
+
+public record DerivationPath
+{
+ public uint Purpose { get; }
+ public uint CoinType { get; }
+ public uint Account { get; }
+
+ private DerivationPath(uint purpose, uint coinType, uint account)
+ {
+ Purpose = purpose;
+ CoinType = coinType;
+ Account = account;
+ }
+
+ public static DerivationPath Create(uint purpose, uint coinType, uint account) =>
+ new(purpose, coinType, account);
+
+ public override string ToString() => $"{Purpose}'{CoinType}'{Account}'";
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/DerivationType.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/DerivationType.cs
new file mode 100644
index 00000000..09a9893d
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/DerivationType.cs
@@ -0,0 +1,7 @@
+namespace Angor.Wallet.Domain;
+
+public enum DerivationType
+{
+ Receive = 0,
+ Change = 1
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/DomainException.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/DomainException.cs
new file mode 100644
index 00000000..ade57682
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/DomainException.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public class DomainException(string message) : Exception(message);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/DomainFeeRate.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/DomainFeeRate.cs
new file mode 100644
index 00000000..b904aea1
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/DomainFeeRate.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record DomainFeeRate(long Value);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/DomainScriptType.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/DomainScriptType.cs
new file mode 100644
index 00000000..e79b11dd
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/DomainScriptType.cs
@@ -0,0 +1,11 @@
+namespace Angor.Wallet.Domain;
+
+public enum DomainScriptType
+{
+ Invalid,
+ SegWit,
+ Taproot,
+ Legacy,
+ P2SH,
+ P2WSH
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/Fee.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/Fee.cs
new file mode 100644
index 00000000..4f799c62
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/Fee.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record Fee(long Value);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/IWalletRepository.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/IWalletRepository.cs
new file mode 100644
index 00000000..e4123ea8
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/IWalletRepository.cs
@@ -0,0 +1,9 @@
+using CSharpFunctionalExtensions;
+
+namespace Angor.Wallet.Domain;
+
+public interface IWalletRepository
+{
+ Task>> ListWallets();
+ Task> Get(WalletId id);
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionAddressInfo.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionAddressInfo.cs
new file mode 100644
index 00000000..a2b152e6
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionAddressInfo.cs
@@ -0,0 +1,6 @@
+namespace Angor.Wallet.Domain;
+
+public record TransactionAddressInfo(
+ string Address,
+ ulong TotalAmount
+);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionInputInfo.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionInputInfo.cs
new file mode 100644
index 00000000..6a99fe9f
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionInputInfo.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record TransactionInputInfo(TransactionAddressInfo Address);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionOutputInfo.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionOutputInfo.cs
new file mode 100644
index 00000000..b67b0413
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/TransactionOutputInfo.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record TransactionOutputInfo(TransactionAddressInfo Address);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/TxId.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/TxId.cs
new file mode 100644
index 00000000..d4e57bea
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/TxId.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public record TxId(string Value);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/Wallet.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/Wallet.cs
new file mode 100644
index 00000000..7583dc60
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/Wallet.cs
@@ -0,0 +1,13 @@
+namespace Angor.Wallet.Domain;
+
+public class Wallet
+{
+ public Wallet(WalletId id, WalletDescriptor descriptor)
+ {
+ Id = id;
+ Descriptor = descriptor;
+ }
+
+ public WalletId Id { get; }
+ public WalletDescriptor Descriptor { get; }
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/WalletDescriptor.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/WalletDescriptor.cs
new file mode 100644
index 00000000..a7b918ab
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/WalletDescriptor.cs
@@ -0,0 +1,3 @@
+namespace Angor.Wallet.Domain;
+
+public sealed record WalletDescriptor(BitcoinNetwork Network, XPubCollection Xpubs);
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/WalletId.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/WalletId.cs
new file mode 100644
index 00000000..ae7fceba
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/WalletId.cs
@@ -0,0 +1,9 @@
+namespace Angor.Wallet.Domain;
+
+public record WalletId(Guid Id)
+{
+ public static WalletId New()
+ {
+ return new WalletId(Guid.NewGuid());
+ }
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/XPub.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/XPub.cs
new file mode 100644
index 00000000..10099af9
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/XPub.cs
@@ -0,0 +1,23 @@
+namespace Angor.Wallet.Domain;
+
+public sealed record XPub
+{
+ public string Value { get; }
+ public DomainScriptType ScriptType { get; }
+ public DerivationPath Path { get; }
+
+ private XPub(string value, DomainScriptType scriptType, DerivationPath path)
+ {
+ Value = value;
+ ScriptType = scriptType;
+ Path = path;
+ }
+
+ public static XPub Create(string value, DomainScriptType scriptType, DerivationPath path)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ throw new DomainException("XPub value cannot be empty");
+
+ return new XPub(value, scriptType, path);
+ }
+}
\ No newline at end of file
diff --git a/src/Angor/Avalonia/Angor.Wallet/Domain/XPubCollection.cs b/src/Angor/Avalonia/Angor.Wallet/Domain/XPubCollection.cs
new file mode 100644
index 00000000..aea001d9
--- /dev/null
+++ b/src/Angor/Avalonia/Angor.Wallet/Domain/XPubCollection.cs
@@ -0,0 +1,5 @@
+using System.Collections.ObjectModel;
+
+namespace Angor.Wallet.Domain;
+
+public class XPubCollection : Collection;
\ No newline at end of file