mirror of
https://github.com/fiatjaf/nak.git
synced 2025-12-08 16:48:51 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df20a3241a | ||
|
|
53a2451303 | ||
|
|
2d992f235e | ||
|
|
7675929056 | ||
|
|
7f608588a2 | ||
|
|
fd5cd55f6f | ||
|
|
932361fe8f | ||
|
|
11ae7bc4d3 | ||
|
|
7033bfee19 | ||
|
|
f425097c5a | ||
|
|
dd0ef2ca64 | ||
|
|
491a094e07 | ||
|
|
9d619ddf00 | ||
|
|
5d32739573 | ||
|
|
a187e448f2 | ||
|
|
9a9e96a829 | ||
|
|
4c6181d649 | ||
|
|
71b106fd45 | ||
|
|
40892c1228 | ||
|
|
847f8aaa69 | ||
|
|
134d1225d6 | ||
|
|
464766a836 | ||
|
|
ea53eca74f | ||
|
|
38ed370c59 | ||
|
|
5b04bc4859 | ||
|
|
2988c71ccb | ||
|
|
d7c0ff2bb7 | ||
|
|
43fe41df5d | ||
|
|
3215726417 | ||
|
|
a4886dc445 | ||
|
|
dae7eba8ca | ||
|
|
2b5f3355bc | ||
|
|
bd5ca27661 | ||
|
|
9d02301b2d | ||
|
|
9bbc87b27a | ||
|
|
88a07a3504 |
9
.github/workflows/release-cli.yml
vendored
9
.github/workflows/release-cli.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
goos: [linux, freebsd, darwin, windows]
|
goos: [linux, freebsd, darwin, windows]
|
||||||
goarch: [amd64, arm64, riscv64]
|
goarch: [arm, amd64, arm64, riscv64]
|
||||||
exclude:
|
exclude:
|
||||||
- goarch: arm64
|
- goarch: arm64
|
||||||
goos: windows
|
goos: windows
|
||||||
@@ -33,6 +33,12 @@ jobs:
|
|||||||
goos: windows
|
goos: windows
|
||||||
- goarch: riscv64
|
- goarch: riscv64
|
||||||
goos: darwin
|
goos: darwin
|
||||||
|
- goarch: arm
|
||||||
|
goos: windows
|
||||||
|
- goarch: arm
|
||||||
|
goos: darwin
|
||||||
|
- goarch: arm
|
||||||
|
goos: freebsd
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: wangyoucao577/go-release-action@v1.40
|
- uses: wangyoucao577/go-release-action@v1.40
|
||||||
@@ -40,6 +46,7 @@ jobs:
|
|||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
goos: ${{ matrix.goos }}
|
goos: ${{ matrix.goos }}
|
||||||
goarch: ${{ matrix.goarch }}
|
goarch: ${{ matrix.goarch }}
|
||||||
|
ldflags: -X main.version=${{ github.ref_name }}
|
||||||
overwrite: true
|
overwrite: true
|
||||||
md5sum: false
|
md5sum: false
|
||||||
sha256sum: false
|
sha256sum: false
|
||||||
|
|||||||
14
bunker.go
14
bunker.go
@@ -2,10 +2,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
"github.com/nbd-wtf/go-nostr/nip19"
|
"github.com/nbd-wtf/go-nostr/nip19"
|
||||||
"github.com/nbd-wtf/go-nostr/nip46"
|
"github.com/nbd-wtf/go-nostr/nip46"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var bunker = &cli.Command{
|
var bunker = &cli.Command{
|
||||||
@@ -50,7 +49,7 @@ var bunker = &cli.Command{
|
|||||||
qs := url.Values{}
|
qs := url.Values{}
|
||||||
relayURLs := make([]string, 0, c.Args().Len())
|
relayURLs := make([]string, 0, c.Args().Len())
|
||||||
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
|
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
|
||||||
_, relays := connectToAllRelays(ctx, relayUrls, false)
|
relays := connectToAllRelays(ctx, relayUrls, false)
|
||||||
if len(relays) == 0 {
|
if len(relays) == 0 {
|
||||||
log("failed to connect to any of the given relays.\n")
|
log("failed to connect to any of the given relays.\n")
|
||||||
os.Exit(3)
|
os.Exit(3)
|
||||||
@@ -143,9 +142,8 @@ var bunker = &cli.Command{
|
|||||||
printBunkerInfo()
|
printBunkerInfo()
|
||||||
|
|
||||||
// subscribe to relays
|
// subscribe to relays
|
||||||
pool := nostr.NewSimplePool(ctx)
|
|
||||||
now := nostr.Now()
|
now := nostr.Now()
|
||||||
events := pool.SubMany(ctx, relayURLs, nostr.Filters{
|
events := sys.Pool.SubMany(ctx, relayURLs, nostr.Filters{
|
||||||
{
|
{
|
||||||
Kinds: []int{nostr.KindNostrConnect},
|
Kinds: []int{nostr.KindNostrConnect},
|
||||||
Tags: nostr.TagMap{"p": []string{pubkey}},
|
Tags: nostr.TagMap{"p": []string{pubkey}},
|
||||||
@@ -184,7 +182,7 @@ var bunker = &cli.Command{
|
|||||||
cancelPreviousBunkerInfoPrint() // this prevents us from printing a million bunker info blocks
|
cancelPreviousBunkerInfoPrint() // this prevents us from printing a million bunker info blocks
|
||||||
|
|
||||||
// handle the NIP-46 request event
|
// handle the NIP-46 request event
|
||||||
req, resp, eventResponse, err := signer.HandleRequest(ie.Event)
|
req, resp, eventResponse, err := signer.HandleRequest(ctx, ie.Event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log("< failed to handle request from %s: %s\n", ie.Event.PubKey, err.Error())
|
log("< failed to handle request from %s: %s\n", ie.Event.PubKey, err.Error())
|
||||||
continue
|
continue
|
||||||
@@ -198,7 +196,7 @@ var bunker = &cli.Command{
|
|||||||
handlerWg.Add(len(relayURLs))
|
handlerWg.Add(len(relayURLs))
|
||||||
for _, relayURL := range relayURLs {
|
for _, relayURL := range relayURLs {
|
||||||
go func(relayURL string) {
|
go func(relayURL string) {
|
||||||
if relay, _ := pool.EnsureRelay(relayURL); relay != nil {
|
if relay, _ := sys.Pool.EnsureRelay(relayURL); relay != nil {
|
||||||
err := relay.Publish(ctx, eventResponse)
|
err := relay.Publish(ctx, eventResponse)
|
||||||
printLock.Lock()
|
printLock.Lock()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -223,7 +221,7 @@ var bunker = &cli.Command{
|
|||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
case <-time.After(time.Minute * 5):
|
case <-time.After(time.Minute * 5):
|
||||||
fmt.Fprintf(os.Stderr, "\n")
|
log("\n")
|
||||||
printBunkerInfo()
|
printBunkerInfo()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
66
count.go
66
count.go
@@ -2,13 +2,14 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fiatjaf/cli/v3"
|
"github.com/fiatjaf/cli/v3"
|
||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip45"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip45/hyperloglog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var count = &cli.Command{
|
var count = &cli.Command{
|
||||||
@@ -66,6 +67,32 @@ var count = &cli.Command{
|
|||||||
},
|
},
|
||||||
ArgsUsage: "[relay...]",
|
ArgsUsage: "[relay...]",
|
||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
|
biggerUrlSize := 0
|
||||||
|
relayUrls := c.Args().Slice()
|
||||||
|
if len(relayUrls) > 0 {
|
||||||
|
relays := connectToAllRelays(ctx,
|
||||||
|
relayUrls,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
if len(relays) == 0 {
|
||||||
|
log("failed to connect to any of the given relays.\n")
|
||||||
|
os.Exit(3)
|
||||||
|
}
|
||||||
|
relayUrls = make([]string, len(relays))
|
||||||
|
for i, relay := range relays {
|
||||||
|
relayUrls[i] = relay.URL
|
||||||
|
if len(relay.URL) > biggerUrlSize {
|
||||||
|
biggerUrlSize = len(relay.URL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
for _, relay := range relays {
|
||||||
|
relay.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
filter := nostr.Filter{}
|
filter := nostr.Filter{}
|
||||||
|
|
||||||
if authors := c.StringSlice("author"); len(authors) > 0 {
|
if authors := c.StringSlice("author"); len(authors) > 0 {
|
||||||
@@ -85,7 +112,7 @@ var count = &cli.Command{
|
|||||||
tags := make([][]string, 0, 5)
|
tags := make([][]string, 0, 5)
|
||||||
for _, tagFlag := range c.StringSlice("tag") {
|
for _, tagFlag := range c.StringSlice("tag") {
|
||||||
spl := strings.SplitN(tagFlag, "=", 2)
|
spl := strings.SplitN(tagFlag, "=", 2)
|
||||||
if len(spl) == 2 && len(spl[0]) == 1 {
|
if len(spl) == 2 {
|
||||||
tags = append(tags, spl)
|
tags = append(tags, spl)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("invalid --tag '%s'", tagFlag)
|
return fmt.Errorf("invalid --tag '%s'", tagFlag)
|
||||||
@@ -119,26 +146,35 @@ var count = &cli.Command{
|
|||||||
filter.Limit = int(limit)
|
filter.Limit = int(limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
relays := c.Args().Slice()
|
|
||||||
successes := 0
|
successes := 0
|
||||||
failures := make([]error, 0, len(relays))
|
if len(relayUrls) > 0 {
|
||||||
if len(relays) > 0 {
|
var hll *hyperloglog.HyperLogLog
|
||||||
for _, relayUrl := range relays {
|
if offset := nip45.HyperLogLogEventPubkeyOffsetForFilter(filter); offset != -1 && len(relayUrls) > 1 {
|
||||||
relay, err := nostr.RelayConnect(ctx, relayUrl)
|
hll = hyperloglog.New(offset)
|
||||||
|
}
|
||||||
|
for _, relayUrl := range relayUrls {
|
||||||
|
relay, _ := sys.Pool.EnsureRelay(relayUrl)
|
||||||
|
count, hllRegisters, err := relay.Count(ctx, nostr.Filters{filter})
|
||||||
|
fmt.Fprintf(os.Stderr, "%s%s: ", strings.Repeat(" ", biggerUrlSize-len(relayUrl)), relayUrl)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
failures = append(failures, err)
|
fmt.Fprintf(os.Stderr, "❌ %s\n", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count, err := relay.Count(ctx, nostr.Filters{filter})
|
|
||||||
if err != nil {
|
var hasHLLStr string
|
||||||
failures = append(failures, err)
|
if hll != nil && len(hllRegisters) == 256 {
|
||||||
continue
|
hll.MergeRegisters(hllRegisters)
|
||||||
|
hasHLLStr = " 📋"
|
||||||
}
|
}
|
||||||
fmt.Printf("%s: %d\n", relay.URL, count)
|
|
||||||
|
fmt.Fprintf(os.Stderr, "%d%s\n", count, hasHLLStr)
|
||||||
successes++
|
successes++
|
||||||
}
|
}
|
||||||
if successes == 0 {
|
if successes == 0 {
|
||||||
return errors.Join(failures...)
|
return fmt.Errorf("all relays have failed")
|
||||||
|
} else if hll != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "📋 HyperLogLog sum: %d\n", hll.Count())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no relays given, will just print the filter
|
// no relays given, will just print the filter
|
||||||
|
|||||||
20
decode.go
20
decode.go
@@ -3,13 +3,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fiatjaf/cli/v3"
|
"github.com/fiatjaf/cli/v3"
|
||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
"github.com/nbd-wtf/go-nostr/nip19"
|
"github.com/nbd-wtf/go-nostr/nip19"
|
||||||
sdk "github.com/nbd-wtf/nostr-sdk"
|
"github.com/nbd-wtf/go-nostr/sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
var decode = &cli.Command{
|
var decode = &cli.Command{
|
||||||
@@ -56,11 +55,22 @@ var decode = &cli.Command{
|
|||||||
}
|
}
|
||||||
} else if evp := sdk.InputToEventPointer(input); evp != nil {
|
} else if evp := sdk.InputToEventPointer(input); evp != nil {
|
||||||
decodeResult = DecodeResult{EventPointer: evp}
|
decodeResult = DecodeResult{EventPointer: evp}
|
||||||
|
if c.Bool("id") {
|
||||||
|
stdout(evp.ID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
} else if pp := sdk.InputToProfile(ctx, input); pp != nil {
|
} else if pp := sdk.InputToProfile(ctx, input); pp != nil {
|
||||||
decodeResult = DecodeResult{ProfilePointer: pp}
|
decodeResult = DecodeResult{ProfilePointer: pp}
|
||||||
|
if c.Bool("pubkey") {
|
||||||
|
stdout(pp.PublicKey)
|
||||||
|
continue
|
||||||
|
}
|
||||||
} else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "naddr" {
|
} else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "naddr" {
|
||||||
ep := value.(nostr.EntityPointer)
|
if ep, ok := value.(nostr.EntityPointer); ok {
|
||||||
decodeResult = DecodeResult{EntityPointer: &ep}
|
decodeResult = DecodeResult{EntityPointer: &ep}
|
||||||
|
} else {
|
||||||
|
ctx = lineProcessingError(ctx, "couldn't decode naddr: %s", err)
|
||||||
|
}
|
||||||
} else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "nsec" {
|
} else if prefix, value, err := nip19.Decode(input); err == nil && prefix == "nsec" {
|
||||||
decodeResult.PrivateKey.PrivateKey = value.(string)
|
decodeResult.PrivateKey.PrivateKey = value.(string)
|
||||||
decodeResult.PrivateKey.PublicKey, _ = nostr.GetPublicKey(value.(string))
|
decodeResult.PrivateKey.PublicKey, _ = nostr.GetPublicKey(value.(string))
|
||||||
@@ -69,6 +79,10 @@ var decode = &cli.Command{
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.Bool("pubkey") || c.Bool("id") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
stdout(decodeResult.JSON())
|
stdout(decodeResult.JSON())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
22
encode.go
22
encode.go
@@ -212,28 +212,6 @@ var encode = &cli.Command{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exitIfLineProcessingError(ctx)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "note",
|
|
||||||
Usage: "generate note1 event codes (not recommended)",
|
|
||||||
DisableSliceFlagSeparator: true,
|
|
||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
|
||||||
for target := range getStdinLinesOrArguments(c.Args()) {
|
|
||||||
if ok := nostr.IsValid32ByteHex(target); !ok {
|
|
||||||
ctx = lineProcessingError(ctx, "invalid event id: %s", target)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if note, err := nip19.EncodeNote(target); err == nil {
|
|
||||||
stdout(note)
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exitIfLineProcessingError(ctx)
|
exitIfLineProcessingError(ctx)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|||||||
140
encrypt_decrypt.go
Normal file
140
encrypt_decrypt.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fiatjaf/cli/v3"
|
||||||
|
"github.com/nbd-wtf/go-nostr"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip04"
|
||||||
|
)
|
||||||
|
|
||||||
|
var encrypt = &cli.Command{
|
||||||
|
Name: "encrypt",
|
||||||
|
Usage: "encrypts a string with nip44 (or nip04 if specified using a flag) and returns the resulting ciphertext as base64",
|
||||||
|
ArgsUsage: "[plaintext string]",
|
||||||
|
DisableSliceFlagSeparator: true,
|
||||||
|
Flags: append(
|
||||||
|
defaultKeyFlags,
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "recipient-pubkey",
|
||||||
|
Aliases: []string{"p", "tgt", "target", "pubkey"},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "nip04",
|
||||||
|
Usage: "use nip04 encryption instead of nip44",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
|
target := c.String("recipient-pubkey")
|
||||||
|
if !nostr.IsValidPublicKey(target) {
|
||||||
|
return fmt.Errorf("target %s is not a valid public key", target)
|
||||||
|
}
|
||||||
|
|
||||||
|
plaintext := c.Args().First()
|
||||||
|
|
||||||
|
if c.Bool("nip04") {
|
||||||
|
sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bunker != nil {
|
||||||
|
ciphertext, err := bunker.NIP04Encrypt(ctx, target, plaintext)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stdout(ciphertext)
|
||||||
|
} else {
|
||||||
|
ss, err := nip04.ComputeSharedSecret(target, sec)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to compute nip04 shared secret: %w", err)
|
||||||
|
}
|
||||||
|
ciphertext, err := nip04.Encrypt(plaintext, ss)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to encrypt as nip04: %w", err)
|
||||||
|
}
|
||||||
|
stdout(ciphertext)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kr, _, err := gatherKeyerFromArguments(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := kr.Encrypt(ctx, plaintext, target)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to encrypt: %w", err)
|
||||||
|
}
|
||||||
|
stdout(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var decrypt = &cli.Command{
|
||||||
|
Name: "decrypt",
|
||||||
|
Usage: "decrypts a base64 nip44 ciphertext (or nip04 if specified using a flag) and returns the resulting plaintext",
|
||||||
|
ArgsUsage: "[ciphertext base64]",
|
||||||
|
DisableSliceFlagSeparator: true,
|
||||||
|
Flags: append(
|
||||||
|
defaultKeyFlags,
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "sender-pubkey",
|
||||||
|
Aliases: []string{"p", "src", "source", "pubkey"},
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "nip04",
|
||||||
|
Usage: "use nip04 encryption instead of nip44",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
|
source := c.String("sender-pubkey")
|
||||||
|
if !nostr.IsValidPublicKey(source) {
|
||||||
|
return fmt.Errorf("source %s is not a valid public key", source)
|
||||||
|
}
|
||||||
|
|
||||||
|
ciphertext := c.Args().First()
|
||||||
|
|
||||||
|
if c.Bool("nip04") {
|
||||||
|
sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bunker != nil {
|
||||||
|
plaintext, err := bunker.NIP04Decrypt(ctx, source, ciphertext)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stdout(plaintext)
|
||||||
|
} else {
|
||||||
|
ss, err := nip04.ComputeSharedSecret(source, sec)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to compute nip04 shared secret: %w", err)
|
||||||
|
}
|
||||||
|
plaintext, err := nip04.Decrypt(ciphertext, ss)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to encrypt as nip04: %w", err)
|
||||||
|
}
|
||||||
|
stdout(plaintext)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kr, _, err := gatherKeyerFromArguments(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := kr.Decrypt(ctx, ciphertext, source)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to encrypt: %w", err)
|
||||||
|
}
|
||||||
|
stdout(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
76
event.go
76
event.go
@@ -2,9 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
"github.com/nbd-wtf/go-nostr/nip13"
|
"github.com/nbd-wtf/go-nostr/nip13"
|
||||||
"github.com/nbd-wtf/go-nostr/nip19"
|
"github.com/nbd-wtf/go-nostr/nip19"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -37,29 +36,7 @@ example:
|
|||||||
echo '{"id":"a889df6a387419ff204305f4c2d296ee328c3cd4f8b62f205648a541b4554dfb","pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","created_at":1698623783,"kind":1,"tags":[],"content":"hello from the nostr army knife","sig":"84876e1ee3e726da84e5d195eb79358b2b3eaa4d9bd38456fde3e8a2af3f1cd4cda23f23fda454869975b3688797d4c66e12f4c51c1b43c6d2997c5e61865661"}' | nak event wss://offchain.pub
|
echo '{"id":"a889df6a387419ff204305f4c2d296ee328c3cd4f8b62f205648a541b4554dfb","pubkey":"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5","created_at":1698623783,"kind":1,"tags":[],"content":"hello from the nostr army knife","sig":"84876e1ee3e726da84e5d195eb79358b2b3eaa4d9bd38456fde3e8a2af3f1cd4cda23f23fda454869975b3688797d4c66e12f4c51c1b43c6d2997c5e61865661"}' | nak event wss://offchain.pub
|
||||||
echo '{"tags": [["t", "spam"]]}' | nak event -c 'this is spam'`,
|
echo '{"tags": [["t", "spam"]]}' | nak event -c 'this is spam'`,
|
||||||
DisableSliceFlagSeparator: true,
|
DisableSliceFlagSeparator: true,
|
||||||
Flags: []cli.Flag{
|
Flags: append(defaultKeyFlags,
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "sec",
|
|
||||||
Usage: "secret key to sign the event, as nsec, ncryptsec or hex",
|
|
||||||
DefaultText: "the key '1'",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "prompt-sec",
|
|
||||||
Usage: "prompt the user to paste a hex or nsec with which to sign the event",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "connect",
|
|
||||||
Usage: "sign event using NIP-46, expects a bunker://... URL",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "connect-as",
|
|
||||||
Usage: "private key to when communicating with the bunker given on --connect",
|
|
||||||
DefaultText: "a random key",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
// ~ these args are only for the convoluted musig2 signing process
|
// ~ these args are only for the convoluted musig2 signing process
|
||||||
// they will be generally copy-shared-pasted across some manual coordination method between participants
|
// they will be generally copy-shared-pasted across some manual coordination method between participants
|
||||||
&cli.UintFlag{
|
&cli.UintFlag{
|
||||||
@@ -125,7 +102,7 @@ example:
|
|||||||
&cli.StringSliceFlag{
|
&cli.StringSliceFlag{
|
||||||
Name: "tag",
|
Name: "tag",
|
||||||
Aliases: []string{"t"},
|
Aliases: []string{"t"},
|
||||||
Usage: "sets a tag field on the event, takes a value like -t e=<id>",
|
Usage: "sets a tag field on the event, takes a value like -t e=<id> or -t sometag=\"value one;value two;value three\"",
|
||||||
Category: CATEGORY_EVENT_FIELDS,
|
Category: CATEGORY_EVENT_FIELDS,
|
||||||
},
|
},
|
||||||
&cli.StringSliceFlag{
|
&cli.StringSliceFlag{
|
||||||
@@ -151,13 +128,13 @@ example:
|
|||||||
Value: nostr.Now(),
|
Value: nostr.Now(),
|
||||||
Category: CATEGORY_EVENT_FIELDS,
|
Category: CATEGORY_EVENT_FIELDS,
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
ArgsUsage: "[relay...]",
|
ArgsUsage: "[relay...]",
|
||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
// try to connect to the relays here
|
// try to connect to the relays here
|
||||||
var relays []*nostr.Relay
|
var relays []*nostr.Relay
|
||||||
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
|
if relayUrls := c.Args().Slice(); len(relayUrls) > 0 {
|
||||||
_, relays = connectToAllRelays(ctx, relayUrls, false)
|
relays = connectToAllRelays(ctx, relayUrls, false)
|
||||||
if len(relays) == 0 {
|
if len(relays) == 0 {
|
||||||
log("failed to connect to any of the given relays.\n")
|
log("failed to connect to any of the given relays.\n")
|
||||||
os.Exit(3)
|
os.Exit(3)
|
||||||
@@ -170,7 +147,7 @@ example:
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
|
kr, sec, err := gatherKeyerFromArguments(ctx, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -248,14 +225,13 @@ example:
|
|||||||
mustRehashAndResign = true
|
mustRehashAndResign = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.IsSet("musig") || c.IsSet("sec") || c.IsSet("prompt-sec") {
|
||||||
|
mustRehashAndResign = true
|
||||||
|
}
|
||||||
|
|
||||||
if difficulty := c.Uint("pow"); difficulty > 0 {
|
if difficulty := c.Uint("pow"); difficulty > 0 {
|
||||||
// before doing pow we need the pubkey
|
// before doing pow we need the pubkey
|
||||||
if bunker != nil {
|
if numSigners := c.Uint("musig"); numSigners > 1 {
|
||||||
evt.PubKey, err = bunker.GetPublicKey(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't pow: failed to get public key from bunker: %w", err)
|
|
||||||
}
|
|
||||||
} else if numSigners := c.Uint("musig"); numSigners > 1 && sec != "" {
|
|
||||||
pubkeys := c.StringSlice("musig-pubkey")
|
pubkeys := c.StringSlice("musig-pubkey")
|
||||||
if int(numSigners) != len(pubkeys) {
|
if int(numSigners) != len(pubkeys) {
|
||||||
return fmt.Errorf("when doing a pow with musig we must know all signer pubkeys upfront")
|
return fmt.Errorf("when doing a pow with musig we must know all signer pubkeys upfront")
|
||||||
@@ -265,7 +241,7 @@ example:
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
evt.PubKey, _ = nostr.GetPublicKey(sec)
|
evt.PubKey, _ = kr.GetPublicKey(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to generate work with this difficulty -- runs forever
|
// try to generate work with this difficulty -- runs forever
|
||||||
@@ -276,11 +252,8 @@ example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if evt.Sig == "" || mustRehashAndResign {
|
if evt.Sig == "" || mustRehashAndResign {
|
||||||
if bunker != nil {
|
if numSigners := c.Uint("musig"); numSigners > 1 {
|
||||||
if err := bunker.SignEvent(ctx, &evt); err != nil {
|
// must do musig
|
||||||
return fmt.Errorf("failed to sign with bunker: %w", err)
|
|
||||||
}
|
|
||||||
} else if numSigners := c.Uint("musig"); numSigners > 1 && sec != "" {
|
|
||||||
pubkeys := c.StringSlice("musig-pubkey")
|
pubkeys := c.StringSlice("musig-pubkey")
|
||||||
secNonce := c.String("musig-nonce-secret")
|
secNonce := c.String("musig-nonce-secret")
|
||||||
pubNonces := c.StringSlice("musig-nonce")
|
pubNonces := c.StringSlice("musig-nonce")
|
||||||
@@ -295,7 +268,7 @@ example:
|
|||||||
// instructions for what to do should have been printed by the performMusig() function
|
// instructions for what to do should have been printed by the performMusig() function
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else if err := evt.Sign(sec); err != nil {
|
} else if err := kr.SignEvent(ctx, &evt); err != nil {
|
||||||
return fmt.Errorf("error signing with provided key: %w", err)
|
return fmt.Errorf("error signing with provided key: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,23 +303,12 @@ example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// error publishing
|
// error publishing
|
||||||
if strings.HasPrefix(err.Error(), "msg: auth-required:") && (sec != "" || bunker != nil) && doAuth {
|
if strings.HasPrefix(err.Error(), "msg: auth-required:") && kr != nil && doAuth {
|
||||||
// if the relay is requesting auth and we can auth, let's do it
|
// if the relay is requesting auth and we can auth, let's do it
|
||||||
var pk string
|
pk, _ := kr.GetPublicKey(ctx)
|
||||||
if bunker != nil {
|
|
||||||
pk, err = bunker.GetPublicKey(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get public key from bunker: %w", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pk, _ = nostr.GetPublicKey(sec)
|
|
||||||
}
|
|
||||||
log("performing auth as %s... ", pk)
|
log("performing auth as %s... ", pk)
|
||||||
if err := relay.Auth(ctx, func(evt *nostr.Event) error {
|
if err := relay.Auth(ctx, func(authEvent *nostr.Event) error {
|
||||||
if bunker != nil {
|
return kr.SignEvent(ctx, authEvent)
|
||||||
return bunker.SignEvent(ctx, evt)
|
|
||||||
}
|
|
||||||
return evt.Sign(sec)
|
|
||||||
}); err == nil {
|
}); err == nil {
|
||||||
// try to publish again, but this time don't try to auth again
|
// try to publish again, but this time don't try to auth again
|
||||||
doAuth = false
|
doAuth = false
|
||||||
|
|||||||
@@ -67,6 +67,20 @@ func ExampleDecode() {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleDecodePubkey() {
|
||||||
|
app.Run(ctx, []string{"nak", "decode", "-p", "npub10xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqpkge6d", "npub1ccz8l9zpa47k6vz9gphftsrumpw80rjt3nhnefat4symjhrsnmjs38mnyd"})
|
||||||
|
// Output:
|
||||||
|
// 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
|
||||||
|
// c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleDecodeEventId() {
|
||||||
|
app.Run(ctx, []string{"nak", "decode", "-e", "nevent1qyd8wumn8ghj7urewfsk66ty9enxjct5dfskvtnrdakj7qgmwaehxw309aex2mrp0yh8wetnw3jhymnzw33jucm0d5hszxthwden5te0wfjkccte9eekummjwsh8xmmrd9skctcpzamhxue69uhkzarvv9ejumn0wd68ytnvv9hxgtcqyqllp5v5j0nxr74fptqxkhvfv0h3uj870qpk3ln8a58agyxl3fka296ewr8", "nevent1qqswh48lurxs8u0pll9qj2rzctvjncwhstpzlstq59rdtzlty79awns5hl5uf"})
|
||||||
|
// Output:
|
||||||
|
// 3ff0d19493e661faa90ac06b5d8963ef1e48fe780368fe67ed0fd410df8a6dd5
|
||||||
|
// ebd4ffe0cd03f1e1ffca092862c2d929e1d782c22fc160a146d58beb278bd74e
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleReq() {
|
func ExampleReq() {
|
||||||
app.Run(ctx, []string{"nak", "req", "-k", "1", "-l", "18", "-a", "2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f", "-e", "aec4de6d051a7c2b6ca2d087903d42051a31e07fb742f1240970084822de10a6"})
|
app.Run(ctx, []string{"nak", "req", "-k", "1", "-l", "18", "-a", "2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f", "-e", "aec4de6d051a7c2b6ca2d087903d42051a31e07fb742f1240970084822de10a6"})
|
||||||
// Output:
|
// Output:
|
||||||
|
|||||||
3
fetch.go
3
fetch.go
@@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
"github.com/nbd-wtf/go-nostr/nip05"
|
"github.com/nbd-wtf/go-nostr/nip05"
|
||||||
"github.com/nbd-wtf/go-nostr/nip19"
|
"github.com/nbd-wtf/go-nostr/nip19"
|
||||||
sdk "github.com/nbd-wtf/nostr-sdk"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var fetch = &cli.Command{
|
var fetch = &cli.Command{
|
||||||
@@ -27,8 +26,6 @@ var fetch = &cli.Command{
|
|||||||
),
|
),
|
||||||
ArgsUsage: "[nip05_or_nip19_code]",
|
ArgsUsage: "[nip05_or_nip19_code]",
|
||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
sys := sdk.NewSystem()
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
sys.Pool.Relays.Range(func(_ string, relay *nostr.Relay) bool {
|
sys.Pool.Relays.Range(func(_ string, relay *nostr.Relay) bool {
|
||||||
relay.Close()
|
relay.Close()
|
||||||
|
|||||||
48
go.mod
48
go.mod
@@ -1,63 +1,61 @@
|
|||||||
module github.com/fiatjaf/nak
|
module github.com/fiatjaf/nak
|
||||||
|
|
||||||
go 1.22
|
go 1.23.1
|
||||||
|
|
||||||
toolchain go1.22.4
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bep/debounce v1.2.1
|
github.com/bep/debounce v1.2.1
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.3.3
|
github.com/btcsuite/btcd/btcec/v2 v2.3.4
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
|
||||||
github.com/fatih/color v1.16.0
|
github.com/fatih/color v1.16.0
|
||||||
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae
|
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae
|
||||||
github.com/fiatjaf/eventstore v0.7.1
|
github.com/fiatjaf/eventstore v0.14.2
|
||||||
github.com/fiatjaf/khatru v0.7.5
|
github.com/fiatjaf/khatru v0.14.0
|
||||||
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/mailru/easyjson v0.7.7
|
github.com/mailru/easyjson v0.7.7
|
||||||
github.com/markusmobius/go-dateparser v1.2.3
|
github.com/markusmobius/go-dateparser v1.2.3
|
||||||
github.com/nbd-wtf/go-nostr v0.34.10
|
github.com/nbd-wtf/go-nostr v0.47.0
|
||||||
github.com/nbd-wtf/nostr-sdk v0.5.0
|
|
||||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
fiatjaf.com/lib v0.2.0 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/btcsuite/btcd/btcutil v1.1.3 // indirect
|
github.com/btcsuite/btcd/btcutil v1.1.3 // indirect
|
||||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
|
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/chzyer/logex v1.1.10 // indirect
|
github.com/chzyer/logex v1.1.10 // indirect
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
|
||||||
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
|
github.com/coder/websocket v1.8.12 // indirect
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.1.0 // indirect
|
||||||
|
github.com/dgraph-io/ristretto v1.0.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/elliotchance/pie/v2 v2.7.0 // indirect
|
github.com/elliotchance/pie/v2 v2.7.0 // indirect
|
||||||
github.com/fasthttp/websocket v1.5.7 // indirect
|
github.com/fasthttp/websocket v1.5.7 // indirect
|
||||||
github.com/fiatjaf/generic-ristretto v0.0.1 // indirect
|
|
||||||
github.com/gobwas/httphead v0.1.0 // indirect
|
|
||||||
github.com/gobwas/pool v0.2.1 // indirect
|
|
||||||
github.com/gobwas/ws v1.4.0 // indirect
|
|
||||||
github.com/golang/glog v1.1.2 // indirect
|
|
||||||
github.com/graph-gophers/dataloader/v7 v7.1.0 // indirect
|
github.com/graph-gophers/dataloader/v7 v7.1.0 // indirect
|
||||||
github.com/hablullah/go-hijri v1.0.2 // indirect
|
github.com/hablullah/go-hijri v1.0.2 // indirect
|
||||||
github.com/hablullah/go-juliandays v1.0.0 // indirect
|
github.com/hablullah/go-juliandays v1.0.0 // indirect
|
||||||
github.com/jalaali/go-jalaali v0.0.0-20210801064154-80525e88d958 // indirect
|
github.com/jalaali/go-jalaali v0.0.0-20210801064154-80525e88d958 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.8 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/magefile/mage v1.14.0 // indirect
|
github.com/magefile/mage v1.14.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/puzpuzpuz/xsync/v3 v3.1.0 // indirect
|
github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect
|
||||||
github.com/rs/cors v1.7.0 // indirect
|
github.com/rs/cors v1.11.1 // indirect
|
||||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
||||||
github.com/tetratelabs/wazero v1.2.1 // indirect
|
github.com/tetratelabs/wazero v1.8.0 // indirect
|
||||||
github.com/tidwall/gjson v1.17.1 // indirect
|
github.com/tidwall/gjson v1.18.0 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||||
github.com/wasilibs/go-re2 v1.3.0 // indirect
|
github.com/wasilibs/go-re2 v1.3.0 // indirect
|
||||||
golang.org/x/crypto v0.21.0 // indirect
|
golang.org/x/crypto v0.32.0 // indirect
|
||||||
golang.org/x/net v0.22.0 // indirect
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d // indirect
|
||||||
golang.org/x/sys v0.22.0 // indirect
|
golang.org/x/net v0.34.0 // indirect
|
||||||
golang.org/x/text v0.16.0 // indirect
|
golang.org/x/sys v0.29.0 // indirect
|
||||||
|
golang.org/x/text v0.21.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
99
go.sum
99
go.sum
@@ -1,3 +1,5 @@
|
|||||||
|
fiatjaf.com/lib v0.2.0 h1:TgIJESbbND6GjOgGHxF5jsO6EMjuAxIzZHPo5DXYexs=
|
||||||
|
fiatjaf.com/lib v0.2.0/go.mod h1:Ycqq3+mJ9jAWu7XjbQI1cVr+OFgnHn79dQR5oTII47g=
|
||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
@@ -8,8 +10,8 @@ github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tj
|
|||||||
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
|
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
|
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0=
|
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||||
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
|
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
|
||||||
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
|
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
|
||||||
github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ=
|
github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ=
|
||||||
@@ -27,27 +29,31 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku
|
|||||||
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||||
|
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||||
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
|
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
|
||||||
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
github.com/dgraph-io/ristretto v1.0.0 h1:SYG07bONKMlFDUYu5pEu3DGAh8c2OFNzKm6G9J4Si84=
|
||||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
github.com/dgraph-io/ristretto v1.0.0/go.mod h1:jTi2FiYEhQ1NsMmA7DeBykizjOuY88NhKBkepyu1jPc=
|
||||||
|
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
|
||||||
|
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/elliotchance/pie/v2 v2.7.0 h1:FqoIKg4uj0G/CrLGuMS9ejnFKa92lxE1dEgBD3pShXg=
|
github.com/elliotchance/pie/v2 v2.7.0 h1:FqoIKg4uj0G/CrLGuMS9ejnFKa92lxE1dEgBD3pShXg=
|
||||||
@@ -58,22 +64,12 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
|||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae h1:0B/1dU3YECIbPoBIRTQ4c0scZCNz9TVHtQpiODGrTTo=
|
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae h1:0B/1dU3YECIbPoBIRTQ4c0scZCNz9TVHtQpiODGrTTo=
|
||||||
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae/go.mod h1:aAWPO4bixZZxPtOnH6K3q4GbQ0jftUNDW9Oa861IRew=
|
github.com/fiatjaf/cli/v3 v3.0.0-20240723181502-e7dd498b16ae/go.mod h1:aAWPO4bixZZxPtOnH6K3q4GbQ0jftUNDW9Oa861IRew=
|
||||||
github.com/fiatjaf/eventstore v0.7.1 h1:5f2yvEtYvsvMBNttysmXhSSum5M1qwvPzjEQ/BFue7Q=
|
github.com/fiatjaf/eventstore v0.14.2 h1:1XOLLEBCGQNQ1rLaO8mcfTQydcetPOqb/uRK8zOnOSI=
|
||||||
github.com/fiatjaf/eventstore v0.7.1/go.mod h1:ek/yWbanKVG767fK51Q3+6Mvi5oEHYSsdPym40nZexw=
|
github.com/fiatjaf/eventstore v0.14.2/go.mod h1:XmYZSdFxsY+cwfpdzVG61M7pemcmqlZwDfDGFC8WwWo=
|
||||||
github.com/fiatjaf/generic-ristretto v0.0.1 h1:LUJSU87X/QWFsBXTwnH3moFe4N8AjUxT+Rfa0+bo6YM=
|
github.com/fiatjaf/khatru v0.14.0 h1:zpWlAA87XBpDKBPIDbAuNw/HpKXzyt5XHVDbSvUbmDo=
|
||||||
github.com/fiatjaf/generic-ristretto v0.0.1/go.mod h1:cvV6ANHDA/GrfzVrig7N7i6l8CWnkVZvtQ2/wk9DPVE=
|
github.com/fiatjaf/khatru v0.14.0/go.mod h1:uxE5e8DBXPZqbHjr/gfatQas5bEJIMmsOCDcdF4LoRQ=
|
||||||
github.com/fiatjaf/khatru v0.7.5 h1:UFo+cdbqHDn1W4Q4h03y3vzh1BiU+6fLYK48oWU2K34=
|
|
||||||
github.com/fiatjaf/khatru v0.7.5/go.mod h1:WVqij7X9Vr9UAMIwafQbKVFKxc42Np37vyficwUr/nQ=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
|
||||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
|
||||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
|
||||||
github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=
|
|
||||||
github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc=
|
|
||||||
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
|
||||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
@@ -85,6 +81,7 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
|||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/graph-gophers/dataloader/v7 v7.1.0 h1:Wn8HGF/q7MNXcvfaBnLEPEFJttVHR8zuEqP1obys/oc=
|
github.com/graph-gophers/dataloader/v7 v7.1.0 h1:Wn8HGF/q7MNXcvfaBnLEPEFJttVHR8zuEqP1obys/oc=
|
||||||
github.com/graph-gophers/dataloader/v7 v7.1.0/go.mod h1:1bKE0Dm6OUcTB/OAuYVOZctgIz7Q3d0XrYtlIzTgg6Q=
|
github.com/graph-gophers/dataloader/v7 v7.1.0/go.mod h1:1bKE0Dm6OUcTB/OAuYVOZctgIz7Q3d0XrYtlIzTgg6Q=
|
||||||
github.com/hablullah/go-hijri v1.0.2 h1:drT/MZpSZJQXo7jftf5fthArShcaMtsal0Zf/dnmp6k=
|
github.com/hablullah/go-hijri v1.0.2 h1:drT/MZpSZJQXo7jftf5fthArShcaMtsal0Zf/dnmp6k=
|
||||||
@@ -99,9 +96,11 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
|
|||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo=
|
github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo=
|
||||||
github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
@@ -113,10 +112,13 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
|||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/nbd-wtf/go-nostr v0.34.10 h1:scJH45sFk5LOzHJNLw0EFTknCCKfKlo3tK+vdpTHz3Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/nbd-wtf/go-nostr v0.34.10/go.mod h1:NZQkxl96ggbO8rvDpVjcsojJqKTPwqhP4i82O7K5DJs=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/nbd-wtf/nostr-sdk v0.5.0 h1:zrMxcvMSxkw29RyfXEdF3XW5rUWLuT5Q9oBAhd5dyew=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/nbd-wtf/nostr-sdk v0.5.0/go.mod h1:MJ7gYv3XiZKU6MHSM0N7oHqQAQhbvpgGQk4Q+XUdIUs=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/nbd-wtf/go-nostr v0.47.0 h1:TM3kf3arDoyVqTmfIbYkgYsKJtIWydMF0zvAbaTenk4=
|
||||||
|
github.com/nbd-wtf/go-nostr v0.47.0/go.mod h1:O6n8bv+KktkEs+4svL7KN/OSnOWB5LzcZbuKjxnpRD0=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
@@ -130,21 +132,22 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/puzpuzpuz/xsync/v3 v3.1.0 h1:EewKT7/LNac5SLiEblJeUu8z5eERHrmRLnMQL2d7qX4=
|
github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
|
||||||
github.com/puzpuzpuz/xsync/v3 v3.1.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
|
||||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
||||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||||
github.com/tetratelabs/wazero v1.2.1 h1:J4X2hrGzJvt+wqltuvcSjHQ7ujQxA9gb6PeMs4qlUWs=
|
github.com/tetratelabs/wazero v1.8.0 h1:iEKu0d4c2Pd+QSRieYbnQC9yiFlMS9D+Jr0LsRmcF4g=
|
||||||
github.com/tetratelabs/wazero v1.2.1/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ=
|
github.com/tetratelabs/wazero v1.8.0/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
|
||||||
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
|
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||||
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
@@ -161,17 +164,17 @@ github.com/wasilibs/nottinygc v0.4.0/go.mod h1:oDcIotskuYNMpqMF23l7Z8uzD4TC0WXHK
|
|||||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w=
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
|
||||||
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -184,13 +187,13 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
147
helpers.go
147
helpers.go
@@ -3,23 +3,34 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"net/textproto"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/chzyer/readline"
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/fiatjaf/cli/v3"
|
"github.com/fiatjaf/cli/v3"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
"github.com/nbd-wtf/go-nostr/nip19"
|
"github.com/nbd-wtf/go-nostr/sdk"
|
||||||
"github.com/nbd-wtf/go-nostr/nip46"
|
|
||||||
"github.com/nbd-wtf/go-nostr/nip49"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var sys = sdk.NewSystem()
|
||||||
|
|
||||||
|
var json = jsoniter.ConfigFastest
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
sys.Pool = nostr.NewSimplePool(context.Background(),
|
||||||
|
nostr.WithRelayOptions(
|
||||||
|
nostr.WithRequestHeader(http.Header{textproto.CanonicalMIMEHeaderKey("user-agent"): {"nak/b"}}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LINE_PROCESSING_ERROR = iota
|
LINE_PROCESSING_ERROR = iota
|
||||||
)
|
)
|
||||||
@@ -66,7 +77,9 @@ func getStdinLinesOrArgumentsFromSlice(args []string) chan string {
|
|||||||
|
|
||||||
// try the stdin
|
// try the stdin
|
||||||
multi := make(chan string)
|
multi := make(chan string)
|
||||||
writeStdinLinesOrNothing(multi)
|
if !writeStdinLinesOrNothing(multi) {
|
||||||
|
close(multi)
|
||||||
|
}
|
||||||
return multi
|
return multi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,13 +133,22 @@ func connectToAllRelays(
|
|||||||
relayUrls []string,
|
relayUrls []string,
|
||||||
forcePreAuth bool,
|
forcePreAuth bool,
|
||||||
opts ...nostr.PoolOption,
|
opts ...nostr.PoolOption,
|
||||||
) (*nostr.SimplePool, []*nostr.Relay) {
|
) []*nostr.Relay {
|
||||||
|
sys.Pool = nostr.NewSimplePool(context.Background(),
|
||||||
|
append(opts,
|
||||||
|
nostr.WithEventMiddleware(sys.TrackEventHints),
|
||||||
|
nostr.WithPenaltyBox(),
|
||||||
|
nostr.WithRelayOptions(
|
||||||
|
nostr.WithRequestHeader(http.Header{textproto.CanonicalMIMEHeaderKey("user-agent"): {"nak/s"}}),
|
||||||
|
),
|
||||||
|
)...,
|
||||||
|
)
|
||||||
|
|
||||||
relays := make([]*nostr.Relay, 0, len(relayUrls))
|
relays := make([]*nostr.Relay, 0, len(relayUrls))
|
||||||
pool := nostr.NewSimplePool(ctx, opts...)
|
|
||||||
relayLoop:
|
relayLoop:
|
||||||
for _, url := range relayUrls {
|
for _, url := range relayUrls {
|
||||||
log("connecting to %s... ", url)
|
log("connecting to %s... ", url)
|
||||||
if relay, err := pool.EnsureRelay(url); err == nil {
|
if relay, err := sys.Pool.EnsureRelay(url); err == nil {
|
||||||
if forcePreAuth {
|
if forcePreAuth {
|
||||||
log("waiting for auth challenge... ")
|
log("waiting for auth challenge... ")
|
||||||
signer := opts[0].(nostr.WithAuthHandler)
|
signer := opts[0].(nostr.WithAuthHandler)
|
||||||
@@ -140,7 +162,7 @@ relayLoop:
|
|||||||
if (*challengeTag)[1] == "" {
|
if (*challengeTag)[1] == "" {
|
||||||
return fmt.Errorf("auth not received yet *****")
|
return fmt.Errorf("auth not received yet *****")
|
||||||
}
|
}
|
||||||
return signer(authEvent)
|
return signer(ctx, nostr.RelayEvent{Event: authEvent, Relay: relay})
|
||||||
}); err == nil {
|
}); err == nil {
|
||||||
// auth succeeded
|
// auth succeeded
|
||||||
break challengeWaitLoop
|
break challengeWaitLoop
|
||||||
@@ -166,7 +188,7 @@ relayLoop:
|
|||||||
log(err.Error() + "\n")
|
log(err.Error() + "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pool, relays
|
return relays
|
||||||
}
|
}
|
||||||
|
|
||||||
func lineProcessingError(ctx context.Context, msg string, args ...any) context.Context {
|
func lineProcessingError(ctx context.Context, msg string, args ...any) context.Context {
|
||||||
@@ -180,109 +202,6 @@ func exitIfLineProcessingError(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) (string, *nip46.BunkerClient, error) {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if bunkerURL := c.String("connect"); bunkerURL != "" {
|
|
||||||
clientKey := c.String("connect-as")
|
|
||||||
if clientKey != "" {
|
|
||||||
clientKey = strings.Repeat("0", 64-len(clientKey)) + clientKey
|
|
||||||
} else {
|
|
||||||
clientKey = nostr.GeneratePrivateKey()
|
|
||||||
}
|
|
||||||
bunker, err := nip46.ConnectBunker(ctx, clientKey, bunkerURL, nil, func(s string) {
|
|
||||||
fmt.Fprintf(color.Error, color.CyanString("[nip46]: open the following URL: %s"), s)
|
|
||||||
})
|
|
||||||
return "", bunker, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// take private from flags, environment variable or default to 1
|
|
||||||
sec := c.String("sec")
|
|
||||||
if sec == "" {
|
|
||||||
if key, ok := os.LookupEnv("NOSTR_SECRET_KEY"); ok {
|
|
||||||
sec = key
|
|
||||||
} else {
|
|
||||||
sec = "0000000000000000000000000000000000000000000000000000000000000001"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Bool("prompt-sec") {
|
|
||||||
if isPiped() {
|
|
||||||
return "", nil, fmt.Errorf("can't prompt for a secret key when processing data from a pipe, try again without --prompt-sec")
|
|
||||||
}
|
|
||||||
sec, err = askPassword("type your secret key as ncryptsec, nsec or hex: ", nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, fmt.Errorf("failed to get secret key: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(sec, "ncryptsec1") {
|
|
||||||
sec, err = promptDecrypt(sec)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, fmt.Errorf("failed to decrypt: %w", err)
|
|
||||||
}
|
|
||||||
} else if bsec, err := hex.DecodeString(leftPadKey(sec)); err == nil {
|
|
||||||
sec = hex.EncodeToString(bsec)
|
|
||||||
} else if prefix, hexvalue, err := nip19.Decode(sec); err != nil {
|
|
||||||
return "", nil, fmt.Errorf("invalid nsec: %w", err)
|
|
||||||
} else if prefix == "nsec" {
|
|
||||||
sec = hexvalue.(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok := nostr.IsValid32ByteHex(sec); !ok {
|
|
||||||
return "", nil, fmt.Errorf("invalid secret key")
|
|
||||||
}
|
|
||||||
|
|
||||||
return sec, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func promptDecrypt(ncryptsec string) (string, error) {
|
|
||||||
for i := 1; i < 4; i++ {
|
|
||||||
var attemptStr string
|
|
||||||
if i > 1 {
|
|
||||||
attemptStr = fmt.Sprintf(" [%d/3]", i)
|
|
||||||
}
|
|
||||||
password, err := askPassword("type the password to decrypt your secret key"+attemptStr+": ", nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
sec, err := nip49.Decrypt(ncryptsec, password)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return sec, nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("couldn't decrypt private key")
|
|
||||||
}
|
|
||||||
|
|
||||||
func askPassword(msg string, shouldAskAgain func(answer string) bool) (string, error) {
|
|
||||||
config := &readline.Config{
|
|
||||||
Stdout: color.Error,
|
|
||||||
Prompt: color.YellowString(msg),
|
|
||||||
InterruptPrompt: "^C",
|
|
||||||
DisableAutoSaveHistory: true,
|
|
||||||
EnableMask: true,
|
|
||||||
MaskRune: '*',
|
|
||||||
}
|
|
||||||
|
|
||||||
rl, err := readline.NewEx(config)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
answer, err := rl.Readline()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
answer = strings.TrimSpace(answer)
|
|
||||||
if shouldAskAgain != nil && shouldAskAgain(answer) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return answer, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|
||||||
func randString(n int) string {
|
func randString(n int) string {
|
||||||
|
|||||||
161
helpers_key.go
Normal file
161
helpers_key.go
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/chzyer/readline"
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"github.com/fiatjaf/cli/v3"
|
||||||
|
"github.com/nbd-wtf/go-nostr"
|
||||||
|
"github.com/nbd-wtf/go-nostr/keyer"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip19"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip46"
|
||||||
|
"github.com/nbd-wtf/go-nostr/nip49"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultKeyFlags = []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "sec",
|
||||||
|
Usage: "secret key to sign the event, as nsec, ncryptsec or hex, or a bunker URL",
|
||||||
|
DefaultText: "the key '1'",
|
||||||
|
Aliases: []string{"connect"},
|
||||||
|
Category: CATEGORY_SIGNER,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "prompt-sec",
|
||||||
|
Usage: "prompt the user to paste a hex or nsec with which to sign the event",
|
||||||
|
Category: CATEGORY_SIGNER,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "connect-as",
|
||||||
|
Usage: "private key to use when communicating with NIP-46 bunkers",
|
||||||
|
DefaultText: "a random key",
|
||||||
|
Category: CATEGORY_SIGNER,
|
||||||
|
Sources: cli.EnvVars("NOSTR_CLIENT_KEY"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func gatherKeyerFromArguments(ctx context.Context, c *cli.Command) (nostr.Keyer, string, error) {
|
||||||
|
key, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var kr nostr.Keyer
|
||||||
|
if bunker != nil {
|
||||||
|
kr = keyer.NewBunkerSignerFromBunkerClient(bunker)
|
||||||
|
} else {
|
||||||
|
kr, err = keyer.NewPlainKeySigner(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return kr, key, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func gatherSecretKeyOrBunkerFromArguments(ctx context.Context, c *cli.Command) (string, *nip46.BunkerClient, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
sec := c.String("sec")
|
||||||
|
if strings.HasPrefix(sec, "bunker://") {
|
||||||
|
// it's a bunker
|
||||||
|
bunkerURL := sec
|
||||||
|
clientKey := c.String("connect-as")
|
||||||
|
if clientKey != "" {
|
||||||
|
clientKey = strings.Repeat("0", 64-len(clientKey)) + clientKey
|
||||||
|
} else {
|
||||||
|
clientKey = nostr.GeneratePrivateKey()
|
||||||
|
}
|
||||||
|
bunker, err := nip46.ConnectBunker(ctx, clientKey, bunkerURL, nil, func(s string) {
|
||||||
|
log(color.CyanString("[nip46]: open the following URL: %s"), s)
|
||||||
|
})
|
||||||
|
return "", bunker, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// take private from flags, environment variable or default to 1
|
||||||
|
if sec == "" {
|
||||||
|
if key, ok := os.LookupEnv("NOSTR_SECRET_KEY"); ok {
|
||||||
|
sec = key
|
||||||
|
} else {
|
||||||
|
sec = "0000000000000000000000000000000000000000000000000000000000000001"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Bool("prompt-sec") {
|
||||||
|
if isPiped() {
|
||||||
|
return "", nil, fmt.Errorf("can't prompt for a secret key when processing data from a pipe, try again without --prompt-sec")
|
||||||
|
}
|
||||||
|
sec, err = askPassword("type your secret key as ncryptsec, nsec or hex: ", nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, fmt.Errorf("failed to get secret key: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(sec, "ncryptsec1") {
|
||||||
|
sec, err = promptDecrypt(sec)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, fmt.Errorf("failed to decrypt: %w", err)
|
||||||
|
}
|
||||||
|
} else if bsec, err := hex.DecodeString(leftPadKey(sec)); err == nil {
|
||||||
|
sec = hex.EncodeToString(bsec)
|
||||||
|
} else if prefix, hexvalue, err := nip19.Decode(sec); err != nil {
|
||||||
|
return "", nil, fmt.Errorf("invalid nsec: %w", err)
|
||||||
|
} else if prefix == "nsec" {
|
||||||
|
sec = hexvalue.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok := nostr.IsValid32ByteHex(sec); !ok {
|
||||||
|
return "", nil, fmt.Errorf("invalid secret key")
|
||||||
|
}
|
||||||
|
|
||||||
|
return sec, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func promptDecrypt(ncryptsec string) (string, error) {
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
var attemptStr string
|
||||||
|
if i > 1 {
|
||||||
|
attemptStr = fmt.Sprintf(" [%d/3]", i)
|
||||||
|
}
|
||||||
|
password, err := askPassword("type the password to decrypt your secret key"+attemptStr+": ", nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
sec, err := nip49.Decrypt(ncryptsec, password)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return sec, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("couldn't decrypt private key")
|
||||||
|
}
|
||||||
|
|
||||||
|
func askPassword(msg string, shouldAskAgain func(answer string) bool) (string, error) {
|
||||||
|
config := &readline.Config{
|
||||||
|
Stdout: color.Error,
|
||||||
|
Prompt: color.YellowString(msg),
|
||||||
|
InterruptPrompt: "^C",
|
||||||
|
DisableAutoSaveHistory: true,
|
||||||
|
EnableMask: true,
|
||||||
|
MaskRune: '*',
|
||||||
|
}
|
||||||
|
|
||||||
|
rl, err := readline.NewEx(config)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
answer, err := rl.Readline()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
answer = strings.TrimSpace(answer)
|
||||||
|
if shouldAskAgain != nil && shouldAskAgain(answer) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return answer, err
|
||||||
|
}
|
||||||
|
}
|
||||||
36
key.go
36
key.go
@@ -3,9 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
@@ -25,8 +23,8 @@ var key = &cli.Command{
|
|||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
generate,
|
generate,
|
||||||
public,
|
public,
|
||||||
encrypt,
|
encryptKey,
|
||||||
decrypt,
|
decryptKey,
|
||||||
combine,
|
combine,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -49,20 +47,28 @@ var public = &cli.Command{
|
|||||||
Description: ``,
|
Description: ``,
|
||||||
ArgsUsage: "[secret]",
|
ArgsUsage: "[secret]",
|
||||||
DisableSliceFlagSeparator: true,
|
DisableSliceFlagSeparator: true,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "with-parity",
|
||||||
|
Usage: "output 33 bytes instead of 32, the first one being either '02' or '03', a prefix indicating whether this pubkey is even or odd.",
|
||||||
|
},
|
||||||
|
},
|
||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
for sec := range getSecretKeysFromStdinLinesOrSlice(ctx, c, c.Args().Slice()) {
|
for sec := range getSecretKeysFromStdinLinesOrSlice(ctx, c, c.Args().Slice()) {
|
||||||
pubkey, err := nostr.GetPublicKey(sec)
|
b, _ := hex.DecodeString(sec)
|
||||||
if err != nil {
|
_, pk := btcec.PrivKeyFromBytes(b)
|
||||||
ctx = lineProcessingError(ctx, "failed to derive public key: %s", err)
|
|
||||||
continue
|
if c.Bool("with-parity") {
|
||||||
|
stdout(hex.EncodeToString(pk.SerializeCompressed()))
|
||||||
|
} else {
|
||||||
|
stdout(hex.EncodeToString(pk.SerializeCompressed()[1:]))
|
||||||
}
|
}
|
||||||
stdout(pubkey)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var encrypt = &cli.Command{
|
var encryptKey = &cli.Command{
|
||||||
Name: "encrypt",
|
Name: "encrypt",
|
||||||
Usage: "encrypts a secret key and prints an ncryptsec code",
|
Usage: "encrypts a secret key and prints an ncryptsec code",
|
||||||
Description: `uses the NIP-49 standard.`,
|
Description: `uses the NIP-49 standard.`,
|
||||||
@@ -101,7 +107,7 @@ var encrypt = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var decrypt = &cli.Command{
|
var decryptKey = &cli.Command{
|
||||||
Name: "decrypt",
|
Name: "decrypt",
|
||||||
Usage: "takes an ncrypsec and a password and decrypts it into an nsec",
|
Usage: "takes an ncrypsec and a password and decrypts it into an nsec",
|
||||||
Description: `uses the NIP-49 standard.`,
|
Description: `uses the NIP-49 standard.`,
|
||||||
@@ -188,7 +194,7 @@ However, if the intent is to check if two existing Nostr pubkeys match a given c
|
|||||||
for i, prefix := range []byte{0x02, 0x03} {
|
for i, prefix := range []byte{0x02, 0x03} {
|
||||||
pubk, err := btcec.ParsePubKey(append([]byte{prefix}, keyb...))
|
pubk, err := btcec.ParsePubKey(append([]byte{prefix}, keyb...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error parsing key %s: %s", keyhex, err)
|
log("error parsing key %s: %s", keyhex, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
group[i] = pubk
|
group[i] = pubk
|
||||||
@@ -229,7 +235,7 @@ However, if the intent is to check if two existing Nostr pubkeys match a given c
|
|||||||
|
|
||||||
agg, _, _, err := musig2.AggregateKeys(combining, true)
|
agg, _, _, err := musig2.AggregateKeys(combining, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error aggregating: %s", err)
|
log("error aggregating: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,13 +258,13 @@ However, if the intent is to check if two existing Nostr pubkeys match a given c
|
|||||||
}
|
}
|
||||||
|
|
||||||
res, _ := json.MarshalIndent(result, "", " ")
|
res, _ := json.MarshalIndent(result, "", " ")
|
||||||
fmt.Println(string(res))
|
stdout(string(res))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSecretKeysFromStdinLinesOrSlice(ctx context.Context, c *cli.Command, keys []string) chan string {
|
func getSecretKeysFromStdinLinesOrSlice(ctx context.Context, _ *cli.Command, keys []string) chan string {
|
||||||
ch := make(chan string)
|
ch := make(chan string)
|
||||||
go func() {
|
go func() {
|
||||||
for sec := range getStdinLinesOrArgumentsFromSlice(keys) {
|
for sec := range getStdinLinesOrArgumentsFromSlice(keys) {
|
||||||
|
|||||||
5
main.go
5
main.go
@@ -7,6 +7,8 @@ import (
|
|||||||
"github.com/fiatjaf/cli/v3"
|
"github.com/fiatjaf/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var version string = "debug"
|
||||||
|
|
||||||
var app = &cli.Command{
|
var app = &cli.Command{
|
||||||
Name: "nak",
|
Name: "nak",
|
||||||
Suggest: true,
|
Suggest: true,
|
||||||
@@ -26,7 +28,10 @@ var app = &cli.Command{
|
|||||||
relay,
|
relay,
|
||||||
bunker,
|
bunker,
|
||||||
serve,
|
serve,
|
||||||
|
encrypt,
|
||||||
|
decrypt,
|
||||||
},
|
},
|
||||||
|
Version: version,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "quiet",
|
Name: "quiet",
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -135,8 +134,8 @@ func performMusig(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "the following code should be saved secretly until the next step an included with --musig-nonce-secret:\n")
|
log("the following code should be saved secretly until the next step an included with --musig-nonce-secret:\n")
|
||||||
fmt.Fprintf(os.Stderr, "%s\n\n", base64.StdEncoding.EncodeToString(nonce.SecNonce[:]))
|
log("%s\n\n", base64.StdEncoding.EncodeToString(nonce.SecNonce[:]))
|
||||||
|
|
||||||
knownNonces = append(knownNonces, nonce.PubNonce)
|
knownNonces = append(knownNonces, nonce.PubNonce)
|
||||||
printPublicCommandForNextPeer(evt, numSigners, knownSigners, knownNonces, nil, false)
|
printPublicCommandForNextPeer(evt, numSigners, knownSigners, knownNonces, nil, false)
|
||||||
@@ -149,7 +148,7 @@ func performMusig(
|
|||||||
} else {
|
} else {
|
||||||
evt.PubKey = hex.EncodeToString(comb.SerializeCompressed()[1:])
|
evt.PubKey = hex.EncodeToString(comb.SerializeCompressed()[1:])
|
||||||
evt.ID = evt.GetID()
|
evt.ID = evt.GetID()
|
||||||
fmt.Fprintf(os.Stderr, "combined key: %x\n\n", comb.SerializeCompressed())
|
log("combined key: %x\n\n", comb.SerializeCompressed())
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have all the signers, which means we must also have all the nonces
|
// we have all the signers, which means we must also have all the nonces
|
||||||
@@ -244,7 +243,7 @@ func printPublicCommandForNextPeer(
|
|||||||
maybeNonceSecret = " --musig-nonce-secret '<insert-nonce-secret>'"
|
maybeNonceSecret = " --musig-nonce-secret '<insert-nonce-secret>'"
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "the next signer and they should call this on their side:\nnak event --sec <insert-secret-key> --musig %d %s%s%s%s%s\n",
|
log("the next signer and they should call this on their side:\nnak event --sec <insert-secret-key> --musig %d %s%s%s%s%s\n",
|
||||||
numSigners,
|
numSigners,
|
||||||
eventToCliArgs(evt),
|
eventToCliArgs(evt),
|
||||||
signersToCliArgs(knownSigners),
|
signersToCliArgs(knownSigners),
|
||||||
|
|||||||
11
paginate.go
11
paginate.go
@@ -9,8 +9,11 @@ import (
|
|||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func paginateWithPoolAndParams(pool *nostr.SimplePool, interval time.Duration, globalLimit uint64) func(ctx context.Context, urls []string, filters nostr.Filters) chan nostr.IncomingEvent {
|
func paginateWithParams(
|
||||||
return func(ctx context.Context, urls []string, filters nostr.Filters) chan nostr.IncomingEvent {
|
interval time.Duration,
|
||||||
|
globalLimit uint64,
|
||||||
|
) func(ctx context.Context, urls []string, filters nostr.Filters, opts ...nostr.SubscriptionOption) chan nostr.RelayEvent {
|
||||||
|
return func(ctx context.Context, urls []string, filters nostr.Filters, opts ...nostr.SubscriptionOption) chan nostr.RelayEvent {
|
||||||
// filters will always be just one
|
// filters will always be just one
|
||||||
filter := filters[0]
|
filter := filters[0]
|
||||||
|
|
||||||
@@ -26,7 +29,7 @@ func paginateWithPoolAndParams(pool *nostr.SimplePool, interval time.Duration, g
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var globalCount uint64 = 0
|
var globalCount uint64 = 0
|
||||||
globalCh := make(chan nostr.IncomingEvent)
|
globalCh := make(chan nostr.RelayEvent)
|
||||||
|
|
||||||
repeatedCache := make([]string, 0, 300)
|
repeatedCache := make([]string, 0, 300)
|
||||||
nextRepeatedCache := make([]string, 0, 300)
|
nextRepeatedCache := make([]string, 0, 300)
|
||||||
@@ -39,7 +42,7 @@ func paginateWithPoolAndParams(pool *nostr.SimplePool, interval time.Duration, g
|
|||||||
time.Sleep(interval)
|
time.Sleep(interval)
|
||||||
|
|
||||||
keepGoing := false
|
keepGoing := false
|
||||||
for evt := range pool.SubManyEose(ctx, urls, nostr.Filters{filter}) {
|
for evt := range sys.Pool.SubManyEose(ctx, urls, nostr.Filters{filter}, opts...) {
|
||||||
if slices.Contains(repeatedCache, evt.ID) {
|
if slices.Contains(repeatedCache, evt.ID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
46
relay.go
46
relay.go
@@ -6,7 +6,6 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -19,9 +18,13 @@ import (
|
|||||||
|
|
||||||
var relay = &cli.Command{
|
var relay = &cli.Command{
|
||||||
Name: "relay",
|
Name: "relay",
|
||||||
Usage: "gets the relay information document for the given relay, as JSON",
|
Usage: "gets the relay information document for the given relay, as JSON -- or allows usage of the relay management API.",
|
||||||
Description: `example:
|
Description: `examples:
|
||||||
nak relay nostr.wine`,
|
fetching relay information:
|
||||||
|
nak relay nostr.wine
|
||||||
|
|
||||||
|
managing a relay
|
||||||
|
nak relay nostr.wine banevent --sec 1234 --id 037eb3751073770ff17483b1b1ff125866cd5147668271975ef0a8a8e7ee184a --reason "I don't like it"`,
|
||||||
ArgsUsage: "<relay-url>",
|
ArgsUsage: "<relay-url>",
|
||||||
DisableSliceFlagSeparator: true,
|
DisableSliceFlagSeparator: true,
|
||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
@@ -74,26 +77,7 @@ var relay = &cli.Command{
|
|||||||
flags[i] = declareFlag(argName)
|
flags[i] = declareFlag(argName)
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = append(flags,
|
flags = append(flags, defaultKeyFlags...)
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "sec",
|
|
||||||
Usage: "secret key to sign the event, as nsec, ncryptsec or hex",
|
|
||||||
DefaultText: "the key '1'",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "prompt-sec",
|
|
||||||
Usage: "prompt the user to paste a hex or nsec with which to sign the event",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "connect",
|
|
||||||
Usage: "sign event using NIP-46, expects a bunker://... URL",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "connect-as",
|
|
||||||
Usage: "private key to when communicating with the bunker given on --connect",
|
|
||||||
DefaultText: "a random key",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
cmd := &cli.Command{
|
cmd := &cli.Command{
|
||||||
Name: def.method,
|
Name: def.method,
|
||||||
@@ -114,7 +98,7 @@ var relay = &cli.Command{
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
|
kr, _, err := gatherKeyerFromArguments(ctx, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -131,7 +115,7 @@ var relay = &cli.Command{
|
|||||||
|
|
||||||
// Authorization
|
// Authorization
|
||||||
payloadHash := sha256.Sum256(reqj)
|
payloadHash := sha256.Sum256(reqj)
|
||||||
authEvent := nostr.Event{
|
tokenEvent := nostr.Event{
|
||||||
Kind: 27235,
|
Kind: 27235,
|
||||||
CreatedAt: nostr.Now(),
|
CreatedAt: nostr.Now(),
|
||||||
Tags: nostr.Tags{
|
Tags: nostr.Tags{
|
||||||
@@ -140,14 +124,10 @@ var relay = &cli.Command{
|
|||||||
{"payload", hex.EncodeToString(payloadHash[:])},
|
{"payload", hex.EncodeToString(payloadHash[:])},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if bunker != nil {
|
if err := kr.SignEvent(ctx, &tokenEvent); err != nil {
|
||||||
if err := bunker.SignEvent(ctx, &authEvent); err != nil {
|
return fmt.Errorf("failed to sign token event: %w", err)
|
||||||
return fmt.Errorf("failed to sign with bunker: %w", err)
|
|
||||||
}
|
}
|
||||||
} else if err := authEvent.Sign(sec); err != nil {
|
evtj, _ := json.Marshal(tokenEvent)
|
||||||
return fmt.Errorf("error signing with provided key: %w", err)
|
|
||||||
}
|
|
||||||
evtj, _ := json.Marshal(authEvent)
|
|
||||||
req.Header.Set("Authorization", "Nostr "+base64.StdEncoding.EncodeToString(evtj))
|
req.Header.Set("Authorization", "Nostr "+base64.StdEncoding.EncodeToString(evtj))
|
||||||
|
|
||||||
// Content-Type
|
// Content-Type
|
||||||
|
|||||||
68
req.go
68
req.go
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -31,7 +30,8 @@ it can also take a filter from stdin, optionally modify it with flags and send i
|
|||||||
example:
|
example:
|
||||||
echo '{"kinds": [1], "#t": ["test"]}' | nak req -l 5 -k 4549 --tag t=spam wss://nostr-pub.wellorder.net`,
|
echo '{"kinds": [1], "#t": ["test"]}' | nak req -l 5 -k 4549 --tag t=spam wss://nostr-pub.wellorder.net`,
|
||||||
DisableSliceFlagSeparator: true,
|
DisableSliceFlagSeparator: true,
|
||||||
Flags: append(reqFilterFlags,
|
Flags: append(defaultKeyFlags,
|
||||||
|
append(reqFilterFlags,
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "stream",
|
Name: "stream",
|
||||||
Usage: "keep the subscription open, printing all events as they are returned",
|
Usage: "keep the subscription open, printing all events as they are returned",
|
||||||
@@ -65,62 +65,32 @@ example:
|
|||||||
Usage: "after connecting, for a NIP-42 \"AUTH\" message to be received, act on it and only then send the \"REQ\"",
|
Usage: "after connecting, for a NIP-42 \"AUTH\" message to be received, act on it and only then send the \"REQ\"",
|
||||||
Category: CATEGORY_SIGNER,
|
Category: CATEGORY_SIGNER,
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
)...,
|
||||||
Name: "sec",
|
|
||||||
Usage: "secret key to sign the AUTH challenge, as hex or nsec",
|
|
||||||
DefaultText: "the key '1'",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "prompt-sec",
|
|
||||||
Usage: "prompt the user to paste a hex or nsec with which to sign the AUTH challenge",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "connect",
|
|
||||||
Usage: "sign AUTH using NIP-46, expects a bunker://... URL",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "connect-as",
|
|
||||||
Usage: "private key to when communicating with the bunker given on --connect",
|
|
||||||
DefaultText: "a random key",
|
|
||||||
Category: CATEGORY_SIGNER,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ArgsUsage: "[relay...]",
|
ArgsUsage: "[relay...]",
|
||||||
Action: func(ctx context.Context, c *cli.Command) error {
|
Action: func(ctx context.Context, c *cli.Command) error {
|
||||||
var pool *nostr.SimplePool
|
|
||||||
|
|
||||||
relayUrls := c.Args().Slice()
|
relayUrls := c.Args().Slice()
|
||||||
if len(relayUrls) > 0 {
|
if len(relayUrls) > 0 {
|
||||||
var relays []*nostr.Relay
|
relays := connectToAllRelays(ctx,
|
||||||
pool, relays = connectToAllRelays(ctx, relayUrls, c.Bool("force-pre-auth"), nostr.WithAuthHandler(func(evt *nostr.Event) error {
|
relayUrls,
|
||||||
|
c.Bool("force-pre-auth"),
|
||||||
|
nostr.WithAuthHandler(
|
||||||
|
func(ctx context.Context, authEvent nostr.RelayEvent) error {
|
||||||
if !c.Bool("auth") && !c.Bool("force-pre-auth") {
|
if !c.Bool("auth") && !c.Bool("force-pre-auth") {
|
||||||
return fmt.Errorf("auth not authorized")
|
return fmt.Errorf("auth not authorized")
|
||||||
}
|
}
|
||||||
sec, bunker, err := gatherSecretKeyOrBunkerFromArguments(ctx, c)
|
kr, _, err := gatherKeyerFromArguments(ctx, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var pk string
|
pk, _ := kr.GetPublicKey(ctx)
|
||||||
if bunker != nil {
|
|
||||||
pk, err = bunker.GetPublicKey(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get public key from bunker: %w", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pk, _ = nostr.GetPublicKey(sec)
|
|
||||||
}
|
|
||||||
log("performing auth as %s... ", pk)
|
log("performing auth as %s... ", pk)
|
||||||
|
|
||||||
if bunker != nil {
|
return kr.SignEvent(ctx, authEvent.Event)
|
||||||
return bunker.SignEvent(ctx, evt)
|
},
|
||||||
} else {
|
),
|
||||||
return evt.Sign(sec)
|
)
|
||||||
}
|
|
||||||
}))
|
|
||||||
if len(relays) == 0 {
|
if len(relays) == 0 {
|
||||||
log("failed to connect to any of the given relays.\n")
|
log("failed to connect to any of the given relays.\n")
|
||||||
os.Exit(3)
|
os.Exit(3)
|
||||||
@@ -151,11 +121,11 @@ example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(relayUrls) > 0 {
|
if len(relayUrls) > 0 {
|
||||||
fn := pool.SubManyEose
|
fn := sys.Pool.SubManyEose
|
||||||
if c.Bool("paginate") {
|
if c.Bool("paginate") {
|
||||||
fn = paginateWithPoolAndParams(pool, c.Duration("paginate-interval"), c.Uint("paginate-global-limit"))
|
fn = paginateWithParams(c.Duration("paginate-interval"), c.Uint("paginate-global-limit"))
|
||||||
} else if c.Bool("stream") {
|
} else if c.Bool("stream") {
|
||||||
fn = pool.SubMany
|
fn = sys.Pool.SubMany
|
||||||
}
|
}
|
||||||
|
|
||||||
for ie := range fn(ctx, relayUrls, nostr.Filters{filter}) {
|
for ie := range fn(ctx, relayUrls, nostr.Filters{filter}) {
|
||||||
@@ -260,8 +230,8 @@ func applyFlagsToFilter(c *cli.Command, filter *nostr.Filter) error {
|
|||||||
}
|
}
|
||||||
tags := make([][]string, 0, 5)
|
tags := make([][]string, 0, 5)
|
||||||
for _, tagFlag := range c.StringSlice("tag") {
|
for _, tagFlag := range c.StringSlice("tag") {
|
||||||
spl := strings.Split(tagFlag, "=")
|
spl := strings.SplitN(tagFlag, "=", 2)
|
||||||
if len(spl) == 2 && len(spl[0]) == 1 {
|
if len(spl) == 2 {
|
||||||
tags = append(tags, spl)
|
tags = append(tags, spl)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("invalid --tag '%s'", tagFlag)
|
return fmt.Errorf("invalid --tag '%s'", tagFlag)
|
||||||
|
|||||||
1
serve.go
1
serve.go
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/fiatjaf/cli/v3"
|
"github.com/fiatjaf/cli/v3"
|
||||||
"github.com/nbd-wtf/go-nostr"
|
"github.com/nbd-wtf/go-nostr"
|
||||||
@@ -32,7 +31,7 @@ it outputs nothing if the verification is successful.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ok, err := evt.CheckSignature(); !ok {
|
if ok, err := evt.CheckSignature(); !ok {
|
||||||
ctx = lineProcessingError(ctx, "invalid signature: %s", err)
|
ctx = lineProcessingError(ctx, "invalid signature: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
zapstore.yaml
Normal file
14
zapstore.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
nak:
|
||||||
|
cli:
|
||||||
|
name: nak
|
||||||
|
summary: a command line tool for doing all things nostr
|
||||||
|
repository: https://github.com/fiatjaf/nak
|
||||||
|
artifacts:
|
||||||
|
nak-v%v-darwin-arm64:
|
||||||
|
platforms: [darwin-arm64]
|
||||||
|
nak-v%v-darwin-amd64:
|
||||||
|
platforms: [darwin-x86_64]
|
||||||
|
nak-v%v-linux-arm64:
|
||||||
|
platforms: [linux-aarch64]
|
||||||
|
nak-v%v-linux-amd64:
|
||||||
|
platforms: [linux-x86_64]
|
||||||
Reference in New Issue
Block a user