Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: app metadata #570

Merged
merged 25 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f724878
chore: wg.Add() before go (#559)
matjaz Aug 28, 2024
6d3e260
chore: code cleanup (#558)
matjaz Aug 28, 2024
f53e9e1
Update README.md
pardus79 Aug 28, 2024
e6285a9
doc: Correct phoenixd install script instructions in readme (#565)
bumi Aug 28, 2024
30ced9b
feat: add migration card in wallet screen (#555)
im-adithya Aug 29, 2024
50fa01e
chore: run extra workflows on PR (#563)
rolznz Aug 29, 2024
0655080
build(deps): bump github.com/nbd-wtf/go-nostr from 0.34.5 to 0.34.10 …
dependabot[bot] Aug 29, 2024
362c83f
build(deps): bump gopkg.in/DataDog/dd-trace-go.v1 from 1.66.0 to 1.67…
dependabot[bot] Aug 29, 2024
8720248
fix: do not render 0 on withdraw onchain funds page when reserve bala…
rolznz Aug 29, 2024
68f13c1
chore: update fly default kill timeout to ensure app gracefully shuts…
rolznz Aug 29, 2024
8cf49e8
feat: app metadata
rolznz Aug 29, 2024
a84b253
fix(wails): parse max length in log output endpoint (#568)
im-adithya Aug 29, 2024
249038a
fix: alby account image and name on transaction list
rolznz Aug 30, 2024
fdfdb6d
fix: vertically center transaction item content
rolznz Aug 30, 2024
365ced1
fix: use slashed zero on wallet balance
rolznz Aug 30, 2024
11b46cf
chore: align app image with app name in transaction list
rolznz Aug 30, 2024
e64adf9
fix: ensure auth with correct user if refresh token expires (#572)
rolznz Aug 30, 2024
37d0f22
fix: do not allow editing name of Alby Account connection
rolznz Aug 30, 2024
45fbd1c
fix: change "Create Wallet" to "Create Subaccount"
rolznz Aug 30, 2024
667f22f
fix: subaccount copy
rolznz Aug 30, 2024
612e8b2
chore: update friends and family app icon
rolznz Aug 31, 2024
a7a887c
fix: update app store images (#574)
im-adithya Aug 31, 2024
dd3d66e
feat: add new auto channel flow that works with existing channels (#556)
rolznz Aug 31, 2024
13eb5c2
feat: new transaction list item design
rolznz Sep 2, 2024
9323c85
Merge remote-tracking branch 'origin/master' into feat/app-metadata
rolznz Sep 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/http.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: HTTP build - Linux and MacOS
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize]
workflow_call:
inputs:
build-release:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/wails.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ name: Wails build - all platforms

on:
push:
branches:
- master
pull_request:
types: [opened, synchronize]

workflow_call:
inputs:
Expand Down
1 change: 1 addition & 0 deletions alby/alby_oauth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.
nil,
scopes,
false,
nil,
)

if err != nil {
Expand Down
25 changes: 24 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
createAppRequest.BudgetRenewal,
expiresAt,
createAppRequest.Scopes,
createAppRequest.Isolated)
createAppRequest.Isolated,
createAppRequest.Metadata)

if err != nil {
return nil, err
Expand Down Expand Up @@ -220,6 +221,16 @@ func (api *api) GetApp(dbApp *db.App) *App {
maxAmount := uint64(paySpecificPermission.MaxAmountSat)
budgetUsage = queries.GetBudgetUsageSat(api.db, &paySpecificPermission)

var metadata Metadata
if dbApp.Metadata != nil {
jsonErr := json.Unmarshal(dbApp.Metadata, &metadata)
if jsonErr != nil {
logger.Logger.WithError(jsonErr).WithFields(logrus.Fields{
"app_id": dbApp.ID,
}).Error("Failed to deserialize app metadata")
}
}

response := App{
ID: dbApp.ID,
Name: dbApp.Name,
Expand All @@ -233,6 +244,7 @@ func (api *api) GetApp(dbApp *db.App) *App {
BudgetUsage: budgetUsage,
BudgetRenewal: paySpecificPermission.BudgetRenewal,
Isolated: dbApp.Isolated,
Metadata: metadata,
}

if dbApp.Isolated {
Expand Down Expand Up @@ -300,6 +312,17 @@ func (api *api) ListApps() ([]App, error) {
apiApp.LastEventAt = &lastEvent.CreatedAt
}

var metadata Metadata
if dbApp.Metadata != nil {
jsonErr := json.Unmarshal(dbApp.Metadata, &metadata)
if jsonErr != nil {
logger.Logger.WithError(jsonErr).WithFields(logrus.Fields{
"app_id": dbApp.ID,
}).Error("Failed to deserialize app metadata")
}
apiApp.Metadata = metadata
}

apiApps = append(apiApps, apiApp)
}
return apiApps, nil
Expand Down
2 changes: 2 additions & 0 deletions api/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type App struct {
BudgetRenewal string `json:"budgetRenewal"`
Isolated bool `json:"isolated"`
Balance uint64 `json:"balance"`
Metadata Metadata `json:"metadata,omitempty"`
}

type ListAppsResponse struct {
Expand All @@ -93,6 +94,7 @@ type CreateAppRequest struct {
Scopes []string `json:"scopes"`
ReturnTo string `json:"returnTo"`
Isolated bool `json:"isolated"`
Metadata Metadata `json:"metadata,omitempty"`
}

type StartRequest struct {
Expand Down
2 changes: 1 addition & 1 deletion cmd/http/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
)

func main() {
log.Info("NWC Starting in HTTP mode")
log.Info("AlbyHub Starting in HTTP mode")

// Create a channel to receive OS signals.
osSignalChannel := make(chan os.Signal, 1)
Expand Down
16 changes: 14 additions & 2 deletions db/db_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package db

import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"slices"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/getAlby/hub/events"
"github.com/getAlby/hub/logger"
"github.com/nbd-wtf/go-nostr"
"gorm.io/datatypes"
"gorm.io/gorm"
)

Expand All @@ -26,7 +28,7 @@ func NewDBService(db *gorm.DB, eventPublisher events.EventPublisher) *dbService
}
}

func (svc *dbService) CreateApp(name string, pubkey string, maxAmountSat uint64, budgetRenewal string, expiresAt *time.Time, scopes []string, isolated bool) (*App, string, error) {
func (svc *dbService) CreateApp(name string, pubkey string, maxAmountSat uint64, budgetRenewal string, expiresAt *time.Time, scopes []string, isolated bool, metadata map[string]interface{}) (*App, string, error) {
if isolated && (slices.Contains(scopes, constants.SIGN_MESSAGE_SCOPE)) {
// cannot sign messages because the isolated app is a custodial subaccount
return nil, "", errors.New("isolated app cannot have sign_message scope")
Expand All @@ -47,7 +49,17 @@ func (svc *dbService) CreateApp(name string, pubkey string, maxAmountSat uint64,
}
}

app := App{Name: name, NostrPubkey: pairingPublicKey, Isolated: isolated}
var metadataBytes []byte
if metadata != nil {
var err error
metadataBytes, err = json.Marshal(metadata)
if err != nil {
logger.Logger.WithError(err).Error("Failed to serialize metadata")
return nil, "", err
}
}

app := App{Name: name, NostrPubkey: pairingPublicKey, Isolated: isolated, Metadata: datatypes.JSON(metadataBytes)}

err := svc.db.Transaction(func(tx *gorm.DB) error {
err := tx.Save(&app).Error
Expand Down
25 changes: 25 additions & 0 deletions db/migrations/202408291715_app_metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package migrations

import (
_ "embed"

"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)

var _202408291715_app_metadata = &gormigrate.Migration{
ID: "202408291715_app_metadata",
Migrate: func(tx *gorm.DB) error {

if err := tx.Exec(`
ALTER TABLE apps ADD COLUMN metadata JSON;
`).Error; err != nil {
return err
}

return nil
},
Rollback: func(tx *gorm.DB) error {
return nil
},
}
1 change: 1 addition & 0 deletions db/migrations/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func Migrate(gormDB *gorm.DB) error {
_202407262257_remove_invalid_scopes,
_202408061737_add_boostagrams_and_use_json,
_202408191242_transaction_failure_reason,
_202408291715_app_metadata,
})

return m.Migrate()
Expand Down
3 changes: 2 additions & 1 deletion db/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type App struct {
CreatedAt time.Time
UpdatedAt time.Time
Isolated bool
Metadata datatypes.JSON
}

type AppPermission struct {
Expand Down Expand Up @@ -86,7 +87,7 @@ type Transaction struct {
}

type DBService interface {
CreateApp(name string, pubkey string, maxAmountSat uint64, budgetRenewal string, expiresAt *time.Time, scopes []string, isolated bool) (*App, string, error)
CreateApp(name string, pubkey string, maxAmountSat uint64, budgetRenewal string, expiresAt *time.Time, scopes []string, isolated bool, metadata map[string]interface{}) (*App, string, error)
}

const (
Expand Down
1 change: 1 addition & 0 deletions fly.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
app = 'nwc'
primary_region = 'lax'
swap_size_mb = 2048
kill_timeout = 120

[build]
image = 'ghcr.io/getalby/hub:latest'
Expand Down
Binary file modified frontend/src/assets/suggested-apps/alby.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/amethyst.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/damus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/habla-news.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/kiwi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/lume.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/nostrudel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/nostur.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/paper-scissors-hodl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/primal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/snort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed frontend/src/assets/suggested-apps/stackernews.png
Binary file not shown.
Binary file modified frontend/src/assets/suggested-apps/uncle-jim.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed frontend/src/assets/suggested-apps/wavelake.png
Binary file not shown.
Binary file added frontend/src/assets/suggested-apps/wavlake.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/wherostr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/yakihonne.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/zap-stream.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/zapplanner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/zapple-pay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/src/assets/suggested-apps/zappy-bird.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 29 additions & 8 deletions frontend/src/components/AppAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
import { suggestedApps } from "src/components/SuggestedAppData";
import UserAvatar from "src/components/UserAvatar";
import { cn } from "src/lib/utils";
import { App } from "src/types";

type Props = {
appName: string;
app: App;
className?: string;
};

export default function AppAvatar({ appName, className }: Props) {
export default function AppAvatar({ app, className }: Props) {
if (app.name === "getalby.com") {
return <UserAvatar className={className} />;
}
const appStoreApp = app?.metadata?.app_store_app_id
? suggestedApps.find(
(suggestedApp) => suggestedApp.id === app.metadata?.app_store_app_id
)
: undefined;
const image = appStoreApp?.logo;

const gradient =
appName
app.name
.split("")
.map((c) => c.charCodeAt(0))
.reduce((a, b) => a + b, 0) % 10;
return (
<div
className={cn(
"rounded-lg border relative",
`avatar-gradient-${gradient}`,
"rounded-lg border relative overflow-hidden",
!image && `avatar-gradient-${gradient}`,
className
)}
>
<span className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white text-xl font-medium capitalize">
{appName.charAt(0)}
</span>
{image && (
<img
src={image}
className={cn("absolute w-full h-full rounded-lg", className)}
/>
)}
{!image && (
<span className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white text-xl font-medium capitalize">
{app.name.charAt(0)}
</span>
)}
</div>
);
}
6 changes: 3 additions & 3 deletions frontend/src/components/SuggestedAppData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import nostur from "src/assets/suggested-apps/nostur.png";
import paperScissorsHodl from "src/assets/suggested-apps/paper-scissors-hodl.png";
import primal from "src/assets/suggested-apps/primal.png";
import snort from "src/assets/suggested-apps/snort.png";
import stackernews from "src/assets/suggested-apps/stackernews.png";
import stackernews from "src/assets/suggested-apps/stacker-news.png";
import uncleJim from "src/assets/suggested-apps/uncle-jim.png";
import wavelake from "src/assets/suggested-apps/wavelake.png";
import wavlake from "src/assets/suggested-apps/wavlake.png";
import wherostr from "src/assets/suggested-apps/wherostr.png";
import yakihonne from "src/assets/suggested-apps/yakihonne.png";
import zapstream from "src/assets/suggested-apps/zap-stream.png";
Expand Down Expand Up @@ -85,7 +85,7 @@ export const suggestedApps: SuggestedApp[] = [
title: "Wavlake",
description: "Creators platform",
webLink: "https://www.wavlake.com/",
logo: wavelake,
logo: wavlake,
},
{
id: "snort",
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/SuggestedApps.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Globe } from "lucide-react";
import { ExternalLinkIcon, Globe } from "lucide-react";
import { Link } from "react-router-dom";
import ExternalLink from "src/components/ExternalLink";
import { AppleIcon } from "src/components/icons/Apple";
Expand Down Expand Up @@ -84,7 +84,7 @@ function InternalAppCard({ id, title, description, logo }: SuggestedApp) {
<CardFooter className="flex flex-row justify-end">
<Link to={`/internal-apps/${id}`}>
<Button variant="outline">
<NostrWalletConnectIcon className="w-4 h-4 mr-2" />
<ExternalLinkIcon className="w-4 h-4 mr-2" />
Open
</Button>
</Link>
Expand Down
Loading
Loading