Skip to content

Commit

Permalink
Changing the npub on opreturn to event id (#177)
Browse files Browse the repository at this point in the history
* Changed the app to use the event id and not the npub when creating and pulling projects

* Added missing end of stream subscription and replaced fixed deserialization issue

* Added type of data stored on the op return

* Fix after rebase

* Applied the changes from the review

* Fixed bug in the script building

* Update src/Angor/Client/Pages/Browse.razor

---------

Co-authored-by: Dan Gershony <[email protected]>
  • Loading branch information
DavidGershony and dangershony authored Nov 29, 2024
1 parent ce85437 commit be9b3e5
Show file tree
Hide file tree
Showing 29 changed files with 377 additions and 327 deletions.
4 changes: 3 additions & 1 deletion src/Angor/Client/Models/FounderProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ public class FounderProject : Project
public int ProjectIndex { get; set; }
public DateTime? LastRequestForSignaturesTime { get; set; }

public string ProjectInfoEventId { get; set; }

public bool NostrMetadataCreated()
{
return !string.IsNullOrEmpty(Metadata?.Name);
}

public bool NostrApplicationSpecificDataCreated()
{
return ProjectInfo?.Stages.Any() ?? false;
return !string.IsNullOrEmpty(ProjectInfoEventId);
}
}
1 change: 1 addition & 0 deletions src/Angor/Client/Models/InvestmentState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ public class InvestmentState
{
public string ProjectIdentifier { get; set; }
public string InvestmentTransactionHash { get; set; }
public string investorPubKey { get; set; }
}
3 changes: 3 additions & 0 deletions src/Angor/Client/Models/InvestorProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class InvestorProject : Project
public long? AmountInvested { get; set; }
public long? AmountInRecovery { get; set; }

public string InvestorPublicKey { get; set; }
public string InvestorNPub { get; set; }

public bool WaitingForFounderResponse()
{
return ReceivedFounderSignatures() == false && SignaturesInfo?.TimeOfSignatureRequest != null;
Expand Down
16 changes: 0 additions & 16 deletions src/Angor/Client/Models/Project.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
using Angor.Shared.Models;
using Angor.Shared.Services;

namespace Angor.Client.Models;

public class Project
{
public Project()
{ }

public Project(ProjectIndexerData indexerData)
{
ProjectInfo = new ProjectInfo
{
ProjectIdentifier = indexerData.ProjectIdentifier,
FounderKey = indexerData.FounderKey,
NostrPubKey = indexerData.NostrPubKey,
};

CreationTransactionId = indexerData.TrxId;
}

public ProjectMetadata? Metadata { get; set; }
public ProjectInfo ProjectInfo { get; set; }

Expand Down
5 changes: 2 additions & 3 deletions src/Angor/Client/NetworkConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Reflection.Metadata.Ecma335;
using Angor.Shared;
using Angor.Shared.Models;
using Angor.Shared.Networks;
using Blockcore.Networks;

namespace Angor.Client;
Expand All @@ -11,8 +9,9 @@ public class NetworkConfiguration : INetworkConfiguration
public static string AngorTestKey = "tpubD8JfN1evVWPoJmLgVg6Usq2HEW9tLqm6CyECAADnH5tyQosrL6NuhpL9X1cQCbSmndVrgLSGGdbRqLfUbE6cRqUbrHtDJgSyQEY2Uu7WwTL";
public static string AngorMainKey = "xpub661MyMwAqRbcGNxKe9aFkPisf3h32gHLJm8f9XAqx8FB1Nk6KngCY8hkhGqxFr2Gyb6yfUaQVbodxLoC1f3K5HU9LM1CXE59gkEXSGCCZ1B";

public static long AngorCreateFeeSats = 10000;
public static long AngorCreateFeeSats = 10001; // versioning :)
public static int AngorInvestFeePercentage = 1;
public static short NostrEventIdKeyType = 1; //TODO David use an enum for this?

public int GetAngorInvestFeePercentage => AngorInvestFeePercentage;

Expand Down
121 changes: 61 additions & 60 deletions src/Angor/Client/Pages/Browse.razor
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,34 @@ else

if (findProject != null)
{
_RelayService.RequestProjectCreateEventsByPubKey(HandleProjectEvents(), StateHasChanged, new[] { findProject.NostrPubKey });

var projectNpub = string.Empty;
_RelayService.LookupProjectsInfoByEventIds<ProjectInfo>(p =>
{
if (SessionStorage.IsProjectInStorageById(p.ProjectIdentifier))
return;
SessionStorage.StoreProject(new Project { ProjectInfo = p, CreationTransactionId = findProject.TrxId });
projectNpub = p.NostrPubKey;
},
() =>
{
_RelayService.LookupNostrProfileForNPub((npub, nostrMetadata) =>
{
var project = SessionStorage.GetProjectById(findProject.ProjectIdentifier);

if (project!.Metadata != null)
return;

project.Metadata = nostrMetadata;
SessionStorage.StoreProject(project);
}, () =>
{
searchInProgress = false;
StateHasChanged();
},
projectNpub);
},
findProject.NostrEventId);
projects = new List<ProjectIndexerData> { findProject };
}
else
Expand Down Expand Up @@ -412,80 +439,54 @@ else
SessionStorage.SetProjectIndexerData(projects);

var projectsForLookup = projectsNotInList
.Where(_ => _.NostrPubKey != null)
.Select(_ => _.NostrPubKey)
.Where(_ => !string.IsNullOrEmpty(_.NostrEventId))
.Select(_ => _.NostrEventId)
.ToArray();

nostrSearchInProgress = true;

if (projectsForLookup.Any())
_RelayService.RequestProjectCreateEventsByPubKey(HandleProjectEvents(), () =>
{
nostrSearchInProgress = false;
StateHasChanged();
}, projectsForLookup);

StateHasChanged();
}
{
var projectNpubsForLookup = new Dictionary<string, string>();

searchInProgress = false;
}
_RelayService.LookupProjectsInfoByEventIds<ProjectInfo>(x =>
{
if (SessionStorage.IsProjectInStorageById(x.ProjectIdentifier))
return;

private Action<NostrEvent> HandleProjectEvents()
{
return e =>
{
var projectIndexerData = projects.FirstOrDefault(x => x.NostrPubKey == e.Pubkey);
var projectIndexerData = projectsNotInList.First(p => p.ProjectIdentifier == x.ProjectIdentifier);

if (projectIndexerData == null && findProject?.NostrPubKey == e.Pubkey)
{
projectIndexerData = findProject;
}
SessionStorage.StoreProject(new Project { ProjectInfo = x, CreationTransactionId = projectIndexerData.TrxId });

switch (e)
{
case { Kind: NostrKind.Metadata }:
projectNpubsForLookup.Add(x.NostrPubKey, projectIndexerData.ProjectIdentifier);

try
{
var nostrMetadata = serializer.Deserialize<ProjectMetadata>(e.Content);
if (projectIndexerData != null)
{
var project = SessionStorage.GetProjectById(projectIndexerData.ProjectIdentifier);
if (project != null)
}, () =>
_RelayService.LookupNostrProfileForNPub((npub, nostrMetadata) =>
{
project.Metadata = nostrMetadata;
SessionStorage.StoreProject(project);
}
}
}
catch (Exception ex)
{
Logger.LogError(ex, $"error parsing the result of kind {NostrKind.Metadata} from relay, ProjectIdentifier = {projectIndexerData?.ProjectIdentifier}");
}
var project = SessionStorage.GetProjectById(projectNpubsForLookup[npub]);
if (project == null)
{
throw new ArgumentOutOfRangeException("Unable to find the project in storage for requested metadata " + npub);
}

break;
case { Kind: NostrKind.ApplicationSpecificData }:
if (project.Metadata != null)
return;

try
{
var projectInfo = serializer.Deserialize<ProjectInfo>(e.Content);
if (projectInfo != null && projectIndexerData != null)
{
if (!SessionStorage.IsProjectInStorageById(projectInfo.ProjectIdentifier))
project.Metadata = nostrMetadata;
SessionStorage.StoreProject(project);
}, () =>
{
SessionStorage.StoreProject(new Project { ProjectInfo = projectInfo, CreationTransactionId = projectIndexerData.TrxId });
}
}
}
catch (Exception ex)
{
Logger.LogError(ex, $"error parsing the result of kind {NostrKind.ApplicationSpecificData} from relay, ProjectIdentifier = {projectIndexerData?.ProjectIdentifier}");
}

break;
nostrSearchInProgress = false;
StateHasChanged();
},
projectNpubsForLookup.Keys.ToArray()),
projectsForLookup);
}
};

StateHasChanged();
}

searchInProgress = false;
}

private void ViewProjectDetails(string projectIdentifier)
Expand Down
3 changes: 2 additions & 1 deletion src/Angor/Client/Pages/Create.razor
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@
if (nostrApplicationSpecificDataCreated == false)
{
nostrApplicationSpecificDataCreated = true;
project.ProjectInfoEventId = _.EventId;
storage.UpdateFounderProject(project);
}

Expand Down Expand Up @@ -792,7 +793,7 @@
feeData.FeeEstimations.Fees.AddRange(fetchFees);
feeData.SelectedFeeEstimation = feeData.FeeEstimations.Fees.First();

unsignedTransaction = _founderTransactionActions.CreateNewProjectTransaction(project.ProjectInfo.FounderKey, _derivationOperations.AngorKeyToScript(project.ProjectInfo.ProjectIdentifier), NetworkConfiguration.AngorCreateFeeSats, project.ProjectInfo.NostrPubKey);
unsignedTransaction = _founderTransactionActions.CreateNewProjectTransaction(project.ProjectInfo.FounderKey, _derivationOperations.AngorKeyToScript(project.ProjectInfo.ProjectIdentifier), NetworkConfiguration.AngorCreateFeeSats, NetworkConfiguration.NostrEventIdKeyType, project.ProjectInfoEventId);

signedTransaction = _WalletOperations.AddInputsAndSignTransaction(accountInfo.GetNextChangeReceiveAddress(), unsignedTransaction, words, accountInfo, feeData.SelectedFeeEstimation);

Expand Down
32 changes: 17 additions & 15 deletions src/Angor/Client/Pages/Invest.razor
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ else
private bool showCreateModal;
TransactionInfo? signedTransaction;
Transaction unSignedTransaction;

string InvestorPubKey;


private FeeData feeData = new();

Expand Down Expand Up @@ -465,9 +466,11 @@ else
var nostrPrivateKeyHex = Encoders.Hex.EncodeData(nostrPrivateKey.ToBytes());

_SignService.LookupSignatureForInvestmentRequest(
NostrPrivateKey.FromHex(nostrPrivateKeyHex).DerivePublicKey().Hex
, project.ProjectInfo.NostrPubKey, investmentProject.SignaturesInfo!.TimeOfSignatureRequest!.Value, investmentProject.SignaturesInfo!.SignatureRequestEventId!,
async _ => await HandleSignatureReceivedAsync(nostrPrivateKeyHex, _));
investmentProject.InvestorNPub,
project.ProjectInfo.NostrPubKey,
investmentProject.SignaturesInfo!.TimeOfSignatureRequest!.Value,
investmentProject.SignaturesInfo!.SignatureRequestEventId!,
signatures => HandleSignatureReceivedAsync(nostrPrivateKeyHex, signatures));
}
catch (Exception e)
{
Expand Down Expand Up @@ -589,14 +592,14 @@ else

var words = await passwordComponent.GetWalletAsync();

var investorKey = _derivationOperations.DeriveInvestorKey(words, project.ProjectInfo.FounderKey);
InvestorPubKey = _derivationOperations.DeriveInvestorKey(words, project.ProjectInfo.FounderKey);

if (Investment.IsSeeder)
{
var seederHash = _derivationOperations.DeriveSeederSecretHash(words, project.ProjectInfo.FounderKey);
}

unSignedTransaction = _InvestorTransactionActions.CreateInvestmentTransaction(project.ProjectInfo, investorKey, Money.Coins(Investment.InvestmentAmount).Satoshi);
unSignedTransaction = _InvestorTransactionActions.CreateInvestmentTransaction(project.ProjectInfo, InvestorPubKey, Money.Coins(Investment.InvestmentAmount).Satoshi);

signedTransaction = _WalletOperations.AddInputsAndSignTransaction(accountInfo.GetNextChangeReceiveAddress(), unSignedTransaction, words, accountInfo, feeData.SelectedFeeEstimation);

Expand Down Expand Up @@ -639,7 +642,7 @@ else
var accountInfo = storage.GetAccountInfo(network.Name);

signedTransaction = _WalletOperations.AddInputsAndSignTransaction(accountInfo.GetNextChangeReceiveAddress(), unSignedTransaction, words, accountInfo, feeData.SelectedFeeEstimation);

StateHasChanged();
}
}
Expand Down Expand Up @@ -670,7 +673,8 @@ else
Metadata = project.Metadata,
SignedTransactionHex = signedTransaction!.Transaction!.ToHex(),
CreationTransactionId = project.CreationTransactionId,
AmountInvested = new Money(Investment.InvestmentAmount, MoneyUnit.BTC).Satoshi
AmountInvested = new Money(Investment.InvestmentAmount, MoneyUnit.BTC).Satoshi,
InvestorPublicKey = InvestorPubKey ?? throw new ArgumentNullException("The investor pub key is not populated")
};

var investorProject = (InvestorProject)project;
Expand Down Expand Up @@ -706,23 +710,21 @@ else

investorProject.SignaturesInfo!.TimeOfSignatureRequest = investmentSigsRequest.eventTime;
investorProject.SignaturesInfo!.SignatureRequestEventId = investmentSigsRequest.eventId;

investorProject.InvestorNPub = NostrPrivateKey.FromHex(nostrPrivateKeyHex).DerivePublicKey().Hex;

storage.AddInvestmentProject(investorProject);
storage.SetNostrPublicKeyPerProject(project.ProjectInfo.ProjectIdentifier, nostrPrivateKey.PubKey.ToHex()[2..]);



foreach (var input in strippedInvestmentTransaction.Inputs)
accountInfo.UtxoReservedForInvestment.Add(input.PrevOut.ToString());

storage.SetAccountInfo(network.Name, accountInfo);

_SignService.LookupSignatureForInvestmentRequest(
NostrPrivateKey.FromHex(nostrPrivateKeyHex).DerivePublicKey().Hex,
investorProject.InvestorNPub,
investorProject.ProjectInfo.NostrPubKey,
investorProject.SignaturesInfo.TimeOfSignatureRequest.Value,
investorProject.SignaturesInfo.SignatureRequestEventId,
async _ => await HandleSignatureReceivedAsync(nostrPrivateKeyHex, _));
signatures => HandleSignatureReceivedAsync(nostrPrivateKeyHex, signatures));

notificationComponent.ShowNotificationMessage("Signature request sent", 5);
}
Expand Down Expand Up @@ -869,7 +871,7 @@ else
{
ProjectIdentifiers = storage.GetInvestmentProjects()
.Where(x => x.InvestedInProject())
.Select(x => new InvestmentState { ProjectIdentifier = x.ProjectInfo.ProjectIdentifier })
.Select(x => new InvestmentState { ProjectIdentifier = x.ProjectInfo.ProjectIdentifier, investorPubKey = x.InvestorPublicKey, InvestmentTransactionHash = x.TransactionId})
.ToList()
};

Expand Down
Loading

0 comments on commit be9b3e5

Please sign in to comment.