[SDK] Persist tx history, vtxos & Provide transaction feed (#354)

* SDK - GetTransactionsStream add to rest/grpc

no session, pattern or user messages provided

* SDK - AppDataRepository added, store refactor

This patch introduces a significant refactor of the Ark SDK codebase. The primary changes involve:

1. **Domain Package Introduction**: A new `domain` package has been created under `store`, encapsulating core data structures and interfaces such as `ConfigData`, `Transaction`, `SdkRepository`, and various repository interfaces. This enhances modularity and separation of concerns.

2. **Replacement of Store with Domain Objects**: All references to the `store` package's `StoreData` have been replaced with `domain.ConfigData`. This change reflects a shift towards using domain-driven design, where the core business logic is represented by domain objects.

3. **Repository Pattern Implementation**: The code has been refactored to use repositories for accessing and managing data. `ConfigRepository` and `TransactionRepository` interfaces are introduced, providing methods for managing configuration data and transactions, respectively.

4. **New Storage Implementations**: New storage implementations using BadgerDB are introduced for persisting transactions (`transaction_repository.go`). This change indicates a move towards more robust and scalable data storage solutions.

5. **Service Layer Introduction**: A service layer (`service.go`) is introduced, which acts as a facade for the underlying data repositories. This layer abstracts the data access logic and provides a unified interface for interacting with configuration and transaction data.

6. **Code Simplification and Cleanup**: The patch removes redundant code and simplifies the existing codebase by consolidating store-related logic and enhancing the overall structure of the code.

7. **Testing Enhancements**: Test cases are updated to reflect the changes in the data access layer, ensuring that the new repository pattern and domain objects are properly tested.

Overall, this refactor aims to improve the maintainability, scalability, and testability of the codebase by adopting best practices such as domain-driven design, repository pattern, and separation of concerns.

* 'SDK listen for tx stream

This diff represents a substantial refactor and enhancement of the `ark-sdk` client, which involves modifications to multiple files, primarily in the `pkg/client-sdk` and `server/internal/core/application` directories. Here's a summary of the key changes:

1. **Configuration and Initialization**:
   - Refactor to replace file-based configuration store with a domain-based approach.
   - Introduced `ListenTransactionStream` configuration to allow real-time transaction event listening.

2. **Client SDK Enhancements**:
   - The client SDK now supports asynchronous transaction streaming and handling.
   - Introduced methods to get transaction event channels and stop the client gracefully.
   - Expanded the `ArkClient` interface to include these new functionalities.

3. **Transaction Handling**:
   - Added support for listening to and processing transaction events in real-time.
   - Implemented methods to handle different types of transactions, including boarding, redeem, and round transactions.
   - Expanded the `Transaction` struct to include more metadata, such as `BoardingVOut`.

4. **Repository Changes**:
   - Introduced `VtxoRepository` for managing VTXO-related operations.
   - Modified `AppDataRepository` to include `VtxoRepository`.

5. **Example and Test Adjustments**:
   - Updated example code to utilize the new transaction streaming capabilities.
   - Adjusted tests to reflect changes in client initialization and configuration handling.

6. **Dependency Updates**:
   - Updated `go.mod` and `go.sum` to include new dependencies such as `badger` for data storage and potentially updated versions of existing packages.

These changes collectively enhance the functionality of the `ark-sdk` client by enabling real-time transaction handling, improving configuration management, and providing a more robust and scalable client architecture. This update seems to be aimed at improving the efficiency and responsiveness of the client application, likely in response to increased demands for real-time data processing and analysis.'

* merge

* go work sync

* test fix

* Tiny refactor (#2)

* tiny refactor

* renaming

* Renamings

* Fixes (#3)

---------

Co-authored-by: Pietralberto Mazza <18440657+altafan@users.noreply.github.com>
This commit is contained in:
Dusan Sekulic
2024-10-17 17:36:48 +02:00
committed by GitHub
parent 03670c9c4b
commit b1c9261f14
44 changed files with 2461 additions and 725 deletions

View File

@@ -13,7 +13,7 @@ import (
"github.com/ark-network/ark/common"
arksdk "github.com/ark-network/ark/pkg/client-sdk"
"github.com/ark-network/ark/pkg/client-sdk/store"
filestore "github.com/ark-network/ark/pkg/client-sdk/store/file"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/btcsuite/btcd/btcutil/psbt"
"github.com/urfave/cli/v2"
"golang.org/x/term"
@@ -213,12 +213,7 @@ func initArkSdk(ctx *cli.Context) error {
}
func config(ctx *cli.Context) error {
cfgStore, err := getConfigStore(ctx.String(datadirFlag.Name))
if err != nil {
return err
}
cfgData, err := cfgStore.GetData(ctx.Context)
cfgData, err := arkSdkClient.GetConfigData(ctx.Context)
if err != nil {
return err
}
@@ -235,6 +230,7 @@ func config(ctx *cli.Context) error {
"boarding_descriptor_template": cfgData.BoardingDescriptorTemplate,
"explorer_url": cfgData.ExplorerURL,
"forfeit_address": cfgData.ForfeitAddress,
"with_transaction_feed": cfgData.WithTransactionFeed,
}
return printJSON(cfg)
@@ -296,16 +292,16 @@ func send(ctx *cli.Context) error {
return fmt.Errorf("missing destination, use --to and --amount or --receivers")
}
configStore, err := getConfigStore(ctx.String(datadirFlag.Name))
configData, err := arkSdkClient.GetConfigData(ctx.Context)
if err != nil {
return err
}
cfgData, err := configStore.GetData(ctx.Context)
net, err := getNetwork(ctx, configData)
if err != nil {
return err
}
net := getNetwork(ctx, cfgData)
isBitcoin := isBtcChain(net)
var receivers []arksdk.Receiver
@@ -378,11 +374,16 @@ func redeem(ctx *cli.Context) error {
}
func getArkSdkClient(ctx *cli.Context) (arksdk.ArkClient, error) {
cfgStore, err := getConfigStore(ctx.String(datadirFlag.Name))
dataDir := ctx.String(datadirFlag.Name)
sdkRepository, err := store.NewStore(store.Config{
ConfigStoreType: types.FileStore,
BaseDir: dataDir,
})
if err != nil {
return nil, err
}
cfgData, err := cfgStore.GetData(ctx.Context)
cfgData, err := sdkRepository.ConfigStore().GetData(context.Background())
if err != nil {
return nil, err
}
@@ -392,41 +393,41 @@ func getArkSdkClient(ctx *cli.Context) (arksdk.ArkClient, error) {
return nil, fmt.Errorf("CLI not initialized, run 'init' cmd to initialize")
}
net := getNetwork(ctx, cfgData)
net, err := getNetwork(ctx, cfgData)
if err != nil {
return nil, err
}
if isBtcChain(net) {
return loadOrCreateClient(
arksdk.LoadCovenantlessClient, arksdk.NewCovenantlessClient, cfgStore,
arksdk.LoadCovenantlessClient, arksdk.NewCovenantlessClient, sdkRepository,
)
}
return loadOrCreateClient(
arksdk.LoadCovenantClient, arksdk.NewCovenantClient, cfgStore,
arksdk.LoadCovenantClient, arksdk.NewCovenantClient, sdkRepository,
)
}
func loadOrCreateClient(
loadFunc, newFunc func(store.ConfigStore) (arksdk.ArkClient, error),
store store.ConfigStore,
loadFunc, newFunc func(types.Store) (arksdk.ArkClient, error),
sdkRepository types.Store,
) (arksdk.ArkClient, error) {
client, err := loadFunc(store)
client, err := loadFunc(sdkRepository)
if err != nil {
if errors.Is(err, arksdk.ErrNotInitialized) {
return newFunc(store)
return newFunc(sdkRepository)
}
return nil, err
}
return client, err
}
func getConfigStore(dataDir string) (store.ConfigStore, error) {
return filestore.NewConfigStore(dataDir)
}
func getNetwork(ctx *cli.Context, configData *store.StoreData) string {
if configData == nil {
return strings.ToLower(ctx.String(networkFlag.Name))
func getNetwork(ctx *cli.Context, cfgData *types.Config) (string, error) {
if cfgData == nil {
return ctx.String(networkFlag.Name), nil
}
return configData.Network.Name
return cfgData.Network.Name, nil
}
func isBtcChain(network string) bool {

View File

@@ -366,6 +366,7 @@ cloud.google.com/go/websecurityscanner v1.6.11/go.mod h1:vhAZjksELSg58EZfUQ1BMEx
cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w=
cloud.google.com/go/workflows v1.12.10 h1:EGJeZmwgE71jxFOI5s9iKST2Bivif3DSzlqVbiXACXQ=
cloud.google.com/go/workflows v1.12.10/go.mod h1:RcKqCiOmKs8wFUEf3EwWZPH5eHc7Oq0kamIyOUCk0IE=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
@@ -393,7 +394,9 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/ClickHouse/clickhouse-go v1.4.3 h1:iAFMa2UrQdR5bHJ2/yaSLffZkxpcOYQMCUuKeNXGdqc=
github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
@@ -401,10 +404,13 @@ github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e h1:n+DcnTNkQ
github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ=
github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82 h1:MG93+PZYs9PyEsj/n5/haQu2gK0h4tUtSy9ejtMwWa0=
github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 h1:cDVUiFo+npB0ZASqnw4q90ylaVAbnYyx0JYqK4YcGok=
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
@@ -418,9 +424,11 @@ github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybF
github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY=
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
github.com/ark-network/ark/api-spec v0.0.0-20240812233307-18e343b31899/go.mod h1:0B5seq/gzuGL8OZGUaO12yj73ZJKAde8L+nmLQAZ7IA=
github.com/ark-network/ark/api-spec v0.0.0-20241009155358-ea5fa2202398/go.mod h1:TRbR7D04k6Tx//Eo/DUay+hFTT42NPCo8RmjcyrQ1DY=
github.com/ark-network/ark/common v0.0.0-20240812222508-b097e943fb45/go.mod h1:8DYeb06Dl8onmrV09xfsdDMGv5HoVtWoKhLBLXOYHew=
github.com/ark-network/ark/common v0.0.0-20240812233307-18e343b31899/go.mod h1:8DYeb06Dl8onmrV09xfsdDMGv5HoVtWoKhLBLXOYHew=
github.com/ark-network/ark/common v0.0.0-20240815203029-edc4534dfc87/go.mod h1:aYAGDfoeBLofnZt9n85wusFyCkrS7hvwdo5TynBlkuY=
github.com/ark-network/ark/common v0.0.0-20241009155358-ea5fa2202398/go.mod h1:zA5/UUj+G/WXDmihyzIVWViTo9rqKf/lb/Mw5MjzusM=
github.com/ark-network/ark/pkg/client-sdk v0.0.0-20240812230256-910716f72d1a/go.mod h1:avKeK73ezowttW3PaycYB4mChaqigAxr4q8pFwIuHww=
github.com/ark-network/ark/pkg/client-sdk v0.0.0-20240913171921-2174e4b04d86/go.mod h1:CRN5aL3u3Q/3tCQLp/ND7NT34/GRsG1ccLk5aX2r7mQ=
github.com/ark-network/ark/server/pkg/kvdb v0.0.0-20240812230256-910716f72d1a/go.mod h1:ivr4Qm16kbJMTovsdscYiV1s1vPOYmEBtp9EgrHFGi4=
@@ -430,6 +438,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IU
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.49.6 h1:yNldzF5kzLBRvKlKz1S0bkvc2+04R1kt13KfBWQBfFA=
github.com/aws/aws-sdk-go v1.49.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk=
@@ -474,22 +484,31 @@ github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240625142744-cc26860b4026/go.mod h
github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcec/v2 v2.2.2/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8=
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0=
github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34=
github.com/btcsuite/btcd/btcutil v1.1.4/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
github.com/btcsuite/btcd/btcutil/psbt v1.1.9/go.mod h1:ehBEvU91lxSlXtA+zZz3iFYx7Yq9eqnKx4/kSrnsvMY=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=
github.com/btcsuite/btcwallet v0.16.10-0.20240706055350-e391a1c31df2/go.mod h1:SLFUSQbP8ON/wxholYMfVLvGPJyk7boczOW/ob+nww4=
github.com/btcsuite/btcwallet/wallet/txauthor v1.2.3/go.mod h1:T2xSiKGpUkSLCh68aF+FMXmKK9mFqNdHl9VaqOr+JjU=
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8=
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0=
github.com/btcsuite/btcwallet/wallet/txrules v1.2.0/go.mod h1:AtkqiL7ccKWxuLYtZm8Bu8G6q82w4yIZdgq6riy60z0=
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk=
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1/go.mod h1:MVSqRkju/IGxImXYPfBkG65FgEZYA4fXchheILMVl8g=
github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs=
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448=
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 h1:nmcKAVTv/cmYrs0A4hbiC6Qw+WTLYy/14SmTt3mLnCo=
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4/go.mod h1:YqJR8WAAHiKIPesZTr9Cx9Az4fRhRLcJ6GcxzRUZCAc=
github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
github.com/btcsuite/btcwallet/wtxmgr v1.5.0/go.mod h1:TQVDhFxseiGtZwEPvLgtfyxuNUDsIdaJdshvWzR0HJ4=
github.com/btcsuite/btcwallet/wtxmgr v1.5.3 h1:QrWCio9Leh3DwkWfp+A1SURj8pYn3JuTLv3waP5uEro=
github.com/btcsuite/btcwallet/wtxmgr v1.5.3/go.mod h1:M4nQpxGTXiDlSOODKXboXX7NFthmiBNjzAKKNS7Fhjg=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4=
github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -513,6 +532,7 @@ github.com/cockroachdb/cockroach-go/v2 v2.1.1 h1:3XzfSMuUT0wBe1a3o5C0eOTcArhmmFA
github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -520,6 +540,7 @@ github.com/coreos/go-etcd v2.0.0+incompatible h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMu
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
@@ -532,17 +553,26 @@ github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369 h1:XNT/Zf5l++1Pyg08
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
github.com/decred/dcrd/lru v1.1.3 h1:w9EAbvGLyzm6jTjF83UKuqZEiUtJmvRhQDOCEIvSuE0=
github.com/decred/dcrd/lru v1.1.3/go.mod h1:Tw0i0pJyiLEx/oZdHLe1Wdv/Y7EGzAX+sYftnmxBR4o=
github.com/dgraph-io/badger/v4 v4.1.0/go.mod h1:P50u28d39ibBRmIJuQC/NSdBOg46HnHw7al2SW5QRHg=
github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs=
github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE=
github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY=
@@ -560,22 +590,47 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
github.com/fergusstrange/embedded-postgres v1.28.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw=
github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8=
github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fsouza/fake-gcs-server v1.17.0 h1:OeH75kBZcZa3ZE+zz/mFdJ2btt9FgqfjI7gIh9+5fvk=
github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw=
github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q=
github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w=
github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
@@ -590,15 +645,18 @@ github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4=
github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4=
github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -606,8 +664,10 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v23.5.9+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI=
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -618,11 +678,13 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
@@ -646,6 +708,7 @@ github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMW
github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8=
github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
@@ -653,12 +716,14 @@ github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
@@ -668,8 +733,10 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
@@ -677,13 +744,18 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w=
github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM=
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0=
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
@@ -691,29 +763,35 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag=
github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgtype v1.14.3 h1:h6W9cPuHsRWQFTWUZMAKMgG5jSwQI0Zurzdvlx3Plus=
github.com/jackc/pgtype v1.14.3/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA=
github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc=
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
@@ -721,10 +799,14 @@ github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad h1:heFfj7z0pGsN
github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jedib0t/go-pretty/v6 v6.2.7 h1:4823Lult/tJ0VI1PgW3aSKw59pMWQ6Kzv9b3Bj6MwY0=
github.com/jedib0t/go-pretty/v6 v6.2.7/go.mod h1:FMkOpgGD3EZ91cW8g/96RfxoV7bdeJyzXPYgz1L1ln0=
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
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/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY=
github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg=
github.com/juju/mgotest v1.0.1 h1:XvuZ2whmkHZ5G+Y/wQaSe28p2FyTwcBaqTzStn+QaLc=
@@ -744,12 +826,16 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8=
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -764,34 +850,48 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc=
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk=
github.com/lightninglabs/neutrino v0.16.0/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk=
github.com/lightninglabs/neutrino/cache v1.1.0/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo=
github.com/lightninglabs/neutrino/cache v1.1.1/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo=
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb h1:yfM05S8DXKhuCBp5qSMZdtSwvJ+GFzl94KbXMNB1JDY=
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI=
github.com/lightningnetwork/lnd v0.18.2-beta h1:Qv4xQ2ka05vqzmdkFdISHCHP6CzHoYNVKfD18XPjHsM=
github.com/lightningnetwork/lnd v0.18.2-beta/go.mod h1:cGQR1cVEZFZQcCx2VBbDY8xwGjCz+SupSopU1HpjP2I=
github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI=
github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U=
github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg=
github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0=
github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ=
github.com/lightningnetwork/lnd/fn v1.0.4/go.mod h1:K9gbvdl5z4XmRcqWUVqvvVcuRKtmq9BNQ+cWYlk+vjw=
github.com/lightningnetwork/lnd/fn v1.1.0/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U=
github.com/lightningnetwork/lnd/kvdb v1.4.10 h1:vK89IVv1oVH9ubQWU+EmoCQFeVRaC8kfmOrqHbY5zoY=
github.com/lightningnetwork/lnd/kvdb v1.4.10/go.mod h1:J2diNABOoII9UrMnxXS5w7vZwP7CA1CStrl8MnIrb3A=
github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms=
github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI=
github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4=
github.com/lightningnetwork/lnd/sqldb v1.0.3 h1:zLfAwOvM+6+3+hahYO9Q3h8pVV0TghAR7iJ5YMLCd3I=
github.com/lightningnetwork/lnd/sqldb v1.0.3/go.mod h1:4cQOkdymlZ1znnjuRNvMoatQGJkRneTj2CoPSPaQhWo=
github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0=
github.com/lightningnetwork/lnd/tlv v1.0.2/go.mod h1:fICAfsqk1IOsC1J7G9IdsWX1EqWRMqEDCNxZJSKr9C4=
github.com/lightningnetwork/lnd/tor v1.1.2/go.mod h1:j7T9uJ2NLMaHwE7GiBGnpYLn4f7NRoTM6qj+ul6/ycA=
github.com/ltcsuite/ltcd v0.23.5 h1:MFWjmx2hCwxrUu9v0wdIPOSN7PHg9BWQeh+AO4FsVLI=
github.com/ltcsuite/ltcd v0.23.5/go.mod h1:JV6swXR5m0cYFi0VYdQPp3UnMdaDQxaRUCaU1PPjb+g=
github.com/ltcsuite/ltcd/btcec/v2 v2.3.2 h1:HVArUNQGqGaSSoyYkk9qGht74U0/uNhS0n7jV9rkmno=
github.com/ltcsuite/ltcd/btcec/v2 v2.3.2/go.mod h1:T1t5TjbjPnryvlGQ+RpSKGuU8KhjNN7rS5+IznPj1VM=
github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 h1:xuWxvRKxLvOKuS7/Q/7I3tpc3cWAB0+hZpU8YdVqkzg=
github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2/go.mod h1:nkLkAFGhursWf2U68gt61hPieK1I+0m78e+2aevNyD8=
github.com/ltcsuite/ltcd/ltcutil v1.1.3 h1:8AapjCPLIt/wtYe6Odfk1EC2y9mcbpgjyxyCoNjAkFI=
github.com/ltcsuite/ltcd/ltcutil v1.1.3/go.mod h1:z8txd/ohBFrOMBUT70K8iZvHJD/Vc3gzx+6BP6cBxQw=
github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/pkger v0.15.1 h1:3MPelV53RnGSW07izx5xGxl4e/sdRD6zqseIk0rMASY=
github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
@@ -801,6 +901,7 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@@ -817,9 +918,13 @@ github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8Ie
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
@@ -840,24 +945,34 @@ github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba h1:fhFP5RliM2HW/8XdcO5QngSfFli9GcRIpMXvypTQt6E=
github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/runc v1.1.13 h1:98S2srgG9vw0zWcDpFMn5TRrh8kLxa/5OFUstuUhmRs=
github.com/opencontainers/runc v1.1.13/go.mod h1:R016aXacfp/gwQBYw2FDGa9m+n6atbLWrYY8hNMT/sA=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/ory/dockertest/v3 v3.11.0 h1:OiHcxKAvSDUwsEVh2BjxQQc/5EHz9n0va9awCtNGuyA=
github.com/ory/dockertest/v3 v3.11.0/go.mod h1:VIPxS1gwT9NpPOrfD3rACs8Y9Z7yhzO4SB194iUDnUI=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pierrec/lz4/v4 v4.1.16 h1:kQPfno+wyx6C5572ABwV+Uo3pDFzQ7yhyGchSyRda0c=
github.com/pierrec/lz4/v4 v4.1.16/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
@@ -865,15 +980,18 @@ github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFu
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
@@ -895,6 +1013,7 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/sagikazarmark/crypt v0.19.0 h1:WMyLTjHBo64UvNcWqpzY3pbZTYgnemZU8FBZigKc42E=
github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78=
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
@@ -909,8 +1028,10 @@ github.com/snowflakedb/gosnowflake v1.6.19 h1:KSHXrQ5o7uso25hNIzi/RObXtnSGkFgie9
github.com/snowflakedb/gosnowflake v1.6.19/go.mod h1:FM1+PWUdwB9udFDsXdfD58NONC0m+MlOSmQRvimobSM=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
@@ -919,20 +1040,27 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/timshannon/badgerhold/v4 v4.0.3 h1:W6pd2qckoXw2cl8eH0ZCV/9CXNaXvaM26tzFi5Tj+v8=
github.com/timshannon/badgerhold/v4 v4.0.3/go.mod h1:IkZIr0kcZLMdD7YJfW/G6epb6ZXHD/h0XR2BTk/VZg8=
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 h1:tcJ6OjwOMvExLlzrAVZute09ocAGa7KqOON60++Gz4E=
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
@@ -943,8 +1071,14 @@ github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJ
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 h1:CTcw80hz/Sw8hqlKX5ZYvBUF5gAHSHwdjXxRf/cjDcI=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:GXBJykxW2kUcktGdsgyay7uwwWvkljASfljNcT0mbh8=
github.com/vulpemventures/go-bip32 v0.0.0-20200624192635-867c159da4d7 h1:X7DtNv+YWy76kELMZB/xVkIJ7YNp2vpgMFVsDcQA40U=
github.com/vulpemventures/go-bip32 v0.0.0-20200624192635-867c159da4d7/go.mod h1:Zrvx8XgpWvSPdz1lXnuN083CkoZnzwxBLEB03S8et1I=
github.com/vulpemventures/go-bip39 v1.0.2 h1:+BgKOVo04okKf1wA4Fhv8ccvql+qFyzVUdVJKkb48r0=
github.com/vulpemventures/go-bip39 v1.0.2/go.mod h1:mjFmuv9D6BtANI6iscMmbHhmBOwjMCFfny3mxHnuDrk=
github.com/vulpemventures/go-elements v0.5.4 h1:l94xoa9aYPPWiOB7Pmi08rKYvdk/n/sQIbLkQfEAASc=
github.com/vulpemventures/go-elements v0.5.4/go.mod h1:Tvhb+rZWv3lxoI5CdK03J3V+e2QVr/7UAnCYILxFSq4=
github.com/xanzy/go-gitlab v0.15.0 h1:rWtwKTgEnXyNUGrOArN7yyc3THRkpYcKXIXia9abywQ=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
@@ -956,8 +1090,11 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
@@ -984,7 +1121,10 @@ go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg=
go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M=
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
@@ -1011,6 +1151,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@@ -1214,6 +1355,7 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec h1:RlWgLqCM
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/juju/environschema.v1 v1.0.0 h1:51vT1bzbP9fntQ0I9ECSlku2p19Szj/N2beZFeIH2kM=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
@@ -1222,6 +1364,7 @@ gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
@@ -1237,6 +1380,7 @@ modernc.org/db v1.0.0 h1:2c6NdCfaLnshSvY7OU09cyAY0gYXUZj4lmg5ItHyucg=
modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=
modernc.org/file v1.0.0 h1:9/PdvjVxd5+LcWUQIfapAWRGOkDLK90rloa8s/au06A=
modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
@@ -1244,15 +1388,19 @@ modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/internal v1.0.0 h1:XMDsFDcBDsibbBnHB2xzljZ+B1yrOVLEFkKL2u15Glw=
modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM=
modernc.org/libc v1.59.3 h1:A4QAp1lRSn2/b4aU+wBtq+yeKgq/2BUevrj0p1ZNy2M=
modernc.org/libc v1.59.3/go.mod h1:EY/egGEU7Ju66eU6SBqCNYaFUDuc4npICkMWnU5EE3A=
modernc.org/lldb v1.0.0 h1:6vjDJxQEfhlOLwl4bhpwIz00uyFK4EmSYcbwqwbynsc=
modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/ql v1.0.0 h1:bIQ/trWNVjQPlinI6jdOQsi195SIturGo3mp5hsDqVU=
modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s=
modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

View File

@@ -4,11 +4,11 @@ import (
"context"
"github.com/ark-network/ark/pkg/client-sdk/client"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
)
type ArkClient interface {
GetConfigData(ctx context.Context) (*store.StoreData, error)
GetConfigData(ctx context.Context) (*types.Config, error)
Init(ctx context.Context, args InitArgs) error
InitWithWallet(ctx context.Context, args InitWithWalletArgs) error
IsLocked(ctx context.Context) bool
@@ -27,8 +27,10 @@ type ArkClient interface {
SendAsync(ctx context.Context, withExpiryCoinselect bool, receivers []Receiver) (string, error)
Claim(ctx context.Context) (string, error)
ListVtxos(ctx context.Context) (spendable, spent []client.Vtxo, err error)
GetTransactionHistory(ctx context.Context) ([]Transaction, error)
Dump(ctx context.Context) (seed string, err error)
GetTransactionHistory(ctx context.Context) ([]types.Transaction, error)
GetTransactionEventChannel() chan types.TransactionEvent
Stop() error
}
type Receiver interface {

View File

@@ -11,7 +11,7 @@ import (
"github.com/ark-network/ark/pkg/client-sdk/client"
"github.com/ark-network/ark/pkg/client-sdk/explorer"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
singlekeywallet "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey"
walletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store"
@@ -28,8 +28,8 @@ const (
// wallet
SingleKeyWallet = wallet.SingleKeyWallet
// store
FileStore = store.FileStore
InMemoryStore = store.InMemoryStore
FileStore = types.FileStore
InMemoryStore = types.InMemoryStore
// explorer
BitcoinExplorer = explorer.BitcoinExplorer
LiquidExplorer = explorer.LiquidExplorer
@@ -53,23 +53,65 @@ var (
)
type arkClient struct {
*store.StoreData
*types.Config
wallet wallet.WalletService
store store.ConfigStore
store types.Store
explorer explorer.Explorer
client client.ASPClient
txStreamCtxCancel context.CancelFunc
}
func (a *arkClient) GetConfigData(
_ context.Context,
) (*store.StoreData, error) {
if a.StoreData == nil {
) (*types.Config, error) {
if a.Config == nil {
return nil, fmt.Errorf("client sdk not initialized")
}
return a.StoreData, nil
return a.Config, nil
}
func (a *arkClient) InitWithWallet(
func (a *arkClient) Unlock(ctx context.Context, pasword string) error {
_, err := a.wallet.Unlock(ctx, pasword)
return err
}
func (a *arkClient) Lock(ctx context.Context, pasword string) error {
return a.wallet.Lock(ctx, pasword)
}
func (a *arkClient) IsLocked(ctx context.Context) bool {
return a.wallet.IsLocked()
}
func (a *arkClient) Dump(ctx context.Context) (string, error) {
return a.wallet.Dump(ctx)
}
func (a *arkClient) Receive(ctx context.Context) (string, string, error) {
offchainAddr, boardingAddr, err := a.wallet.NewAddress(ctx, false)
if err != nil {
return "", "", err
}
return offchainAddr, boardingAddr, nil
}
func (a *arkClient) GetTransactionEventChannel() chan types.TransactionEvent {
return a.store.TransactionStore().GetEventChannel()
}
func (a *arkClient) Stop() error {
if a.Config.WithTransactionFeed {
a.txStreamCtxCancel()
}
a.store.Close()
return nil
}
func (a *arkClient) initWithWallet(
ctx context.Context, args InitWithWalletArgs,
) error {
if err := args.validate(); err != nil {
@@ -104,7 +146,7 @@ func (a *arkClient) InitWithWallet(
return fmt.Errorf("failed to parse asp pubkey: %s", err)
}
storeData := store.StoreData{
storeData := types.Config{
AspUrl: args.AspUrl,
AspPubkey: aspPubkey,
WalletType: args.Wallet.GetType(),
@@ -116,18 +158,19 @@ func (a *arkClient) InitWithWallet(
Dust: info.Dust,
BoardingDescriptorTemplate: info.BoardingDescriptorTemplate,
ForfeitAddress: info.ForfeitAddress,
WithTransactionFeed: args.ListenTransactionStream,
}
if err := a.store.AddData(ctx, storeData); err != nil {
if err := a.store.ConfigStore().AddData(ctx, storeData); err != nil {
return err
}
if _, err := args.Wallet.Create(ctx, args.Password, args.Seed); err != nil {
//nolint:all
a.store.CleanData(ctx)
a.store.ConfigStore().CleanData(ctx)
return err
}
a.StoreData = &storeData
a.Config = &storeData
a.wallet = args.Wallet
a.explorer = explorerSvc
a.client = clientSvc
@@ -135,7 +178,7 @@ func (a *arkClient) InitWithWallet(
return nil
}
func (a *arkClient) Init(
func (a *arkClient) init(
ctx context.Context, args InitArgs,
) error {
if err := args.validate(); err != nil {
@@ -170,7 +213,7 @@ func (a *arkClient) Init(
return fmt.Errorf("failed to parse asp pubkey: %s", err)
}
storeData := store.StoreData{
cfgData := types.Config{
AspUrl: args.AspUrl,
AspPubkey: aspPubkey,
WalletType: args.WalletType,
@@ -183,23 +226,24 @@ func (a *arkClient) Init(
BoardingDescriptorTemplate: info.BoardingDescriptorTemplate,
ExplorerURL: args.ExplorerURL,
ForfeitAddress: info.ForfeitAddress,
WithTransactionFeed: args.ListenTransactionStream,
}
walletSvc, err := getWallet(a.store, &storeData, supportedWallets)
walletSvc, err := getWallet(a.store.ConfigStore(), &cfgData, supportedWallets)
if err != nil {
return err
}
if err := a.store.AddData(ctx, storeData); err != nil {
if err := a.store.ConfigStore().AddData(ctx, cfgData); err != nil {
return err
}
if _, err := walletSvc.Create(ctx, args.Password, args.Seed); err != nil {
//nolint:all
a.store.CleanData(ctx)
a.store.ConfigStore().CleanData(ctx)
return err
}
a.StoreData = &storeData
a.Config = &cfgData
a.wallet = walletSvc
a.explorer = explorerSvc
a.client = clientSvc
@@ -207,32 +251,6 @@ func (a *arkClient) Init(
return nil
}
func (a *arkClient) Unlock(ctx context.Context, pasword string) error {
_, err := a.wallet.Unlock(ctx, pasword)
return err
}
func (a *arkClient) Lock(ctx context.Context, pasword string) error {
return a.wallet.Lock(ctx, pasword)
}
func (a *arkClient) IsLocked(ctx context.Context) bool {
return a.wallet.IsLocked()
}
func (a *arkClient) Dump(ctx context.Context) (string, error) {
return a.wallet.Dump(ctx)
}
func (a *arkClient) Receive(ctx context.Context) (string, string, error) {
offchainAddr, boardingAddr, err := a.wallet.NewAddress(ctx, false)
if err != nil {
return "", "", err
}
return offchainAddr, boardingAddr, nil
}
func (a *arkClient) ping(
ctx context.Context, paymentID string,
) func() {
@@ -270,11 +288,11 @@ func getExplorer(explorerURL, network string) (explorer.Explorer, error) {
}
func getWallet(
storeSvc store.ConfigStore, data *store.StoreData, supportedWallets utils.SupportedType[struct{}],
configStore types.ConfigStore, data *types.Config, supportedWallets utils.SupportedType[struct{}],
) (wallet.WalletService, error) {
switch data.WalletType {
case wallet.SingleKeyWallet:
return getSingleKeyWallet(storeSvc, data.Network.Name)
return getSingleKeyWallet(configStore, data.Network.Name)
default:
return nil, fmt.Errorf(
"unsuported wallet type '%s', please select one of: %s",
@@ -284,12 +302,13 @@ func getWallet(
}
func getSingleKeyWallet(
configStore store.ConfigStore, network string,
configStore types.ConfigStore, network string,
) (wallet.WalletService, error) {
walletStore, err := getWalletStore(configStore.GetType(), configStore.GetDatadir())
if err != nil {
return nil, err
}
if strings.Contains(network, "liquid") {
return singlekeywallet.NewLiquidWallet(configStore, walletStore)
}
@@ -298,9 +317,9 @@ func getSingleKeyWallet(
func getWalletStore(storeType, datadir string) (walletstore.WalletStore, error) {
switch storeType {
case store.InMemoryStore:
case types.InMemoryStore:
return inmemorystore.NewWalletStore()
case store.FileStore:
case types.FileStore:
return filestore.NewWalletStore(datadir)
default:
return nil, fmt.Errorf("unknown wallet store type")

View File

@@ -50,6 +50,7 @@ type ASPClient interface {
GetRound(ctx context.Context, txID string) (*Round, error)
GetRoundByID(ctx context.Context, roundID string) (*Round, error)
Close()
GetTransactionsStream(ctx context.Context) (<-chan TransactionEvent, func(), error)
}
type Info struct {
@@ -170,3 +171,22 @@ type RoundSigningNoncesGeneratedEvent struct {
}
func (e RoundSigningNoncesGeneratedEvent) isRoundEvent() {}
type TransactionEvent struct {
Round *RoundTransaction
Redeem *RedeemTransaction
Err error
}
type RoundTransaction struct {
Txid string
SpentVtxos []Outpoint
SpendableVtxos []Vtxo
ClaimedBoardingUtxos []Outpoint
}
type RedeemTransaction struct {
Txid string
SpentVtxos []Outpoint
SpendableVtxos []Vtxo
}

View File

@@ -5,6 +5,7 @@ import (
"context"
"encoding/hex"
"fmt"
"io"
"strings"
"time"
@@ -329,3 +330,88 @@ func (c *grpcClient) Close() {
//nolint:all
c.conn.Close()
}
func (c *grpcClient) GetTransactionsStream(
ctx context.Context,
) (<-chan client.TransactionEvent, func(), error) {
stream, err := c.svc.GetTransactionsStream(ctx, &arkv1.GetTransactionsStreamRequest{})
if err != nil {
return nil, nil, err
}
eventCh := make(chan client.TransactionEvent)
go func() {
defer close(eventCh)
for {
resp, err := stream.Recv()
if err == io.EOF {
return
}
if err != nil {
eventCh <- client.TransactionEvent{Err: err}
return
}
switch tx := resp.Tx.(type) {
case *arkv1.GetTransactionsStreamResponse_Round:
eventCh <- client.TransactionEvent{
Round: &client.RoundTransaction{
Txid: tx.Round.Txid,
SpentVtxos: outpointsFromProto(tx.Round.SpentVtxos),
SpendableVtxos: vtxosFromProto(tx.Round.SpendableVtxos),
ClaimedBoardingUtxos: outpointsFromProto(tx.Round.ClaimedBoardingUtxos),
},
}
case *arkv1.GetTransactionsStreamResponse_Redeem:
eventCh <- client.TransactionEvent{
Redeem: &client.RedeemTransaction{
Txid: tx.Redeem.Txid,
SpentVtxos: outpointsFromProto(tx.Redeem.SpentVtxos),
SpendableVtxos: vtxosFromProto(tx.Redeem.SpendableVtxos),
},
}
}
}
}()
closeFn := func() {
if err := stream.CloseSend(); err != nil {
logrus.Warnf("failed to close stream: %v", err)
}
}
return eventCh, closeFn, nil
}
func outpointsFromProto(protoOutpoints []*arkv1.Outpoint) []client.Outpoint {
outpoints := make([]client.Outpoint, len(protoOutpoints))
for i, o := range protoOutpoints {
outpoints[i] = client.Outpoint{
Txid: o.Txid,
VOut: o.Vout,
}
}
return outpoints
}
func vtxosFromProto(protoVtxos []*arkv1.Vtxo) []client.Vtxo {
vtxos := make([]client.Vtxo, len(protoVtxos))
for i, v := range protoVtxos {
expiresAt := time.Unix(v.ExpireAt, 0)
vtxos[i] = client.Vtxo{
Outpoint: client.Outpoint{
Txid: v.Outpoint.Txid,
VOut: v.Outpoint.Vout,
},
Descriptor: v.Descriptor_,
Amount: v.Amount,
RoundTxid: v.RoundTxid,
ExpiresAt: &expiresAt,
RedeemTx: v.RedeemTx,
Pending: v.Pending,
SpentBy: v.SpentBy,
}
}
return vtxos
}

View File

@@ -615,3 +615,94 @@ func (t treeFromProto) parse() tree.CongestionTree {
return congestionTree
}
func (c *restClient) GetTransactionsStream(ctx context.Context) (<-chan client.TransactionEvent, func(), error) {
ctx, cancel := context.WithTimeout(ctx, c.requestTimeout)
eventsCh := make(chan client.TransactionEvent)
go func() {
ticker := time.NewTicker(1 * time.Second)
defer close(eventsCh)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
resp, err := c.svc.ArkServiceGetTransactionsStream(ark_service.NewArkServiceGetTransactionsStreamParams())
if err != nil {
eventsCh <- client.TransactionEvent{Err: err}
return
}
if resp.Payload.Result.Round != nil {
eventsCh <- client.TransactionEvent{
Round: &client.RoundTransaction{
Txid: resp.Payload.Result.Round.Txid,
SpentVtxos: outpointsFromRest(resp.Payload.Result.Round.SpentVtxos),
SpendableVtxos: vtxosFromRest(resp.Payload.Result.Round.SpendableVtxos),
ClaimedBoardingUtxos: outpointsFromRest(resp.Payload.Result.Round.ClaimedBoardingUtxos),
},
}
} else if resp.Payload.Result.Redeem != nil {
eventsCh <- client.TransactionEvent{
Redeem: &client.RedeemTransaction{
Txid: resp.Payload.Result.Redeem.Txid,
SpentVtxos: outpointsFromRest(resp.Payload.Result.Redeem.SpentVtxos),
SpendableVtxos: vtxosFromRest(resp.Payload.Result.Redeem.SpendableVtxos),
},
}
}
}
}
}()
return eventsCh, cancel, nil
}
func outpointsFromRest(restOutpoints []*models.V1Outpoint) []client.Outpoint {
outpoints := make([]client.Outpoint, len(restOutpoints))
for i, o := range restOutpoints {
outpoints[i] = client.Outpoint{
Txid: o.Txid,
VOut: uint32(o.Vout),
}
}
return outpoints
}
func vtxosFromRest(restVtxos []*models.V1Vtxo) []client.Vtxo {
vtxos := make([]client.Vtxo, len(restVtxos))
for i, v := range restVtxos {
var expiresAt *time.Time
if v.ExpireAt != "" && v.ExpireAt != "0" {
expAt, err := strconv.Atoi(v.ExpireAt)
if err != nil {
return nil
}
t := time.Unix(int64(expAt), 0)
expiresAt = &t
}
amount, err := strconv.Atoi(v.Amount)
if err != nil {
return nil
}
vtxos[i] = client.Vtxo{
Outpoint: client.Outpoint{
Txid: v.Outpoint.Txid,
VOut: uint32(v.Outpoint.Vout),
},
Descriptor: v.Descriptor,
Amount: uint64(amount),
RoundTxid: v.RoundTxid,
ExpiresAt: expiresAt,
RedeemTx: v.RedeemTx,
Pending: v.Pending,
SpentBy: v.SpentBy,
}
}
return vtxos
}

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/ark-network/ark/pkg/client-sdk/client"
sdktypes "github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/stretchr/testify/require"
)
@@ -15,90 +16,106 @@ func TestVtxosToTxs(t *testing.T) {
tests := []struct {
name string
fixture string
want []Transaction
want []sdktypes.Transaction
}{
{
name: "Alice Before Sending Async",
fixture: aliceBeforeSendingAsync,
want: []Transaction{},
want: []sdktypes.Transaction{},
},
{
name: "Alice After Sending Async",
fixture: aliceAfterSendingAsync,
want: []Transaction{
want: []sdktypes.Transaction{
{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
Amount: 1000,
Type: TxSent,
IsPending: false,
CreatedAt: time.Unix(1726054898, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
},
Amount: 1000,
Type: sdktypes.TxSent,
IsPending: false,
CreatedAt: time.Unix(1726054898, 0),
},
},
},
{
name: "Bob Before Claiming Async",
fixture: bobBeforeClaimingAsync,
want: []Transaction{
want: []sdktypes.Transaction{
{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
Amount: 1000,
Type: TxReceived,
IsPending: true,
CreatedAt: time.Unix(1726054898, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
},
Amount: 1000,
Type: sdktypes.TxReceived,
IsPending: true,
CreatedAt: time.Unix(1726054898, 0),
},
{
RedeemTxid: "766fc46ba5c2da41cd4c4bc0566e0f4e0f24c184c41acd3bead5cd7b11120367",
Amount: 2000,
Type: TxReceived,
IsPending: true,
CreatedAt: time.Unix(1726486359, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "766fc46ba5c2da41cd4c4bc0566e0f4e0f24c184c41acd3bead5cd7b11120367",
},
Amount: 2000,
Type: sdktypes.TxReceived,
IsPending: true,
CreatedAt: time.Unix(1726486359, 0),
},
},
},
{
name: "Bob After Claiming Async",
fixture: bobAfterClaimingAsync,
want: []Transaction{
want: []sdktypes.Transaction{
{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
Amount: 1000,
Type: TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726054898, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
},
Amount: 1000,
Type: sdktypes.TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726054898, 0),
},
{
RedeemTxid: "766fc46ba5c2da41cd4c4bc0566e0f4e0f24c184c41acd3bead5cd7b11120367",
Amount: 2000,
Type: TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726486359, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "766fc46ba5c2da41cd4c4bc0566e0f4e0f24c184c41acd3bead5cd7b11120367",
},
Amount: 2000,
Type: sdktypes.TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726486359, 0),
},
},
},
{
name: "Bob After Sending Async",
fixture: bobAfterSendingAsync,
want: []Transaction{
want: []sdktypes.Transaction{
{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
Amount: 1000,
Type: TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726054898, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
},
Amount: 1000,
Type: sdktypes.TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726054898, 0),
},
{
RedeemTxid: "766fc46ba5c2da41cd4c4bc0566e0f4e0f24c184c41acd3bead5cd7b11120367",
Amount: 2000,
Type: TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726486359, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "766fc46ba5c2da41cd4c4bc0566e0f4e0f24c184c41acd3bead5cd7b11120367",
},
Amount: 2000,
Type: sdktypes.TxReceived,
IsPending: false,
CreatedAt: time.Unix(1726486359, 0),
},
{
RedeemTxid: "23c3a885f0ea05f7bdf83f3bf7f8ac9dc3f791ad292f4e63a6f53fa5e4935ab0",
Amount: 2100,
Type: TxSent,
IsPending: false,
CreatedAt: time.Unix(1726503865, 0),
TransactionKey: sdktypes.TransactionKey{
RedeemTxid: "23c3a885f0ea05f7bdf83f3bf7f8ac9dc3f791ad292f4e63a6f53fa5e4935ab0",
},
Amount: 2100,
Type: sdktypes.TxSent,
IsPending: false,
CreatedAt: time.Unix(1726503865, 0),
},
},
},

View File

@@ -17,7 +17,7 @@ import (
"github.com/ark-network/ark/pkg/client-sdk/explorer"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/redemption"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/chaincfg/chainhash"
@@ -56,86 +56,199 @@ type covenantArkClient struct {
*arkClient
}
func NewCovenantClient(storeSvc store.ConfigStore) (ArkClient, error) {
data, err := storeSvc.GetData(context.Background())
func NewCovenantClient(sdkStore types.Store) (ArkClient, error) {
cfgData, err := sdkStore.ConfigStore().GetData(context.Background())
if err != nil {
return nil, err
}
if data != nil {
if cfgData != nil {
return nil, ErrAlreadyInitialized
}
return &covenantArkClient{&arkClient{store: storeSvc}}, nil
return &covenantArkClient{
&arkClient{
store: sdkStore,
},
}, nil
}
func LoadCovenantClient(storeSvc store.ConfigStore) (ArkClient, error) {
if storeSvc == nil {
return nil, fmt.Errorf("missin store service")
func LoadCovenantClient(sdkStore types.Store) (ArkClient, error) {
if sdkStore == nil {
return nil, fmt.Errorf("missin sdk repository")
}
data, err := storeSvc.GetData(context.Background())
cfgData, err := sdkStore.ConfigStore().GetData(context.Background())
if err != nil {
return nil, err
}
if data == nil {
if cfgData == nil {
return nil, ErrNotInitialized
}
clientSvc, err := getClient(
supportedClients, data.ClientType, data.AspUrl,
supportedClients, cfgData.ClientType, cfgData.AspUrl,
)
if err != nil {
return nil, fmt.Errorf("failed to setup transport client: %s", err)
}
explorerSvc, err := getExplorer(data.ExplorerURL, data.Network.Name)
explorerSvc, err := getExplorer(cfgData.ExplorerURL, cfgData.Network.Name)
if err != nil {
return nil, fmt.Errorf("failed to setup explorer: %s", err)
}
walletSvc, err := getWallet(storeSvc, data, supportedWallets)
walletSvc, err := getWallet(
sdkStore.ConfigStore(),
cfgData,
supportedWallets,
)
if err != nil {
return nil, fmt.Errorf("faile to setup wallet: %s", err)
}
return &covenantArkClient{
&arkClient{data, walletSvc, storeSvc, explorerSvc, clientSvc},
}, nil
covenantClient := covenantArkClient{
&arkClient{
Config: cfgData,
wallet: walletSvc,
store: sdkStore,
explorer: explorerSvc,
client: clientSvc,
},
}
if cfgData.WithTransactionFeed {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
covenantClient.txStreamCtxCancel = txStreamCtxCancel
go covenantClient.listenForTxStream(txStreamCtx)
go covenantClient.listenForBoardingUtxos(txStreamCtx)
}
return &covenantClient, nil
}
func LoadCovenantClientWithWallet(
storeSvc store.ConfigStore, walletSvc wallet.WalletService,
sdkStore types.Store, walletSvc wallet.WalletService,
) (ArkClient, error) {
if storeSvc == nil {
return nil, fmt.Errorf("missin store service")
if sdkStore == nil {
return nil, fmt.Errorf("missin sdk repository")
}
if walletSvc == nil {
return nil, fmt.Errorf("missin wallet service")
}
data, err := storeSvc.GetData(context.Background())
cfgData, err := sdkStore.ConfigStore().GetData(context.Background())
if err != nil {
return nil, err
}
if data == nil {
if cfgData == nil {
return nil, ErrNotInitialized
}
clientSvc, err := getClient(
supportedClients, data.ClientType, data.AspUrl,
supportedClients, cfgData.ClientType, cfgData.AspUrl,
)
if err != nil {
return nil, fmt.Errorf("failed to setup transport client: %s", err)
}
explorerSvc, err := getExplorer(data.ExplorerURL, data.Network.Name)
explorerSvc, err := getExplorer(cfgData.ExplorerURL, cfgData.Network.Name)
if err != nil {
return nil, fmt.Errorf("failed to setup explorer: %s", err)
}
return &covenantArkClient{
&arkClient{data, walletSvc, storeSvc, explorerSvc, clientSvc},
}, nil
covenantClient := covenantArkClient{
&arkClient{
Config: cfgData,
wallet: walletSvc,
store: sdkStore,
explorer: explorerSvc,
client: clientSvc,
},
}
if cfgData.WithTransactionFeed {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
covenantClient.txStreamCtxCancel = txStreamCtxCancel
go covenantClient.listenForTxStream(txStreamCtx)
go covenantClient.listenForBoardingUtxos(txStreamCtx)
}
return &covenantClient, nil
}
func (a *covenantArkClient) Init(ctx context.Context, args InitArgs) error {
err := a.arkClient.init(ctx, args)
if err != nil {
return err
}
if args.ListenTransactionStream {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
a.txStreamCtxCancel = txStreamCtxCancel
go a.listenForTxStream(txStreamCtx)
go a.listenForBoardingUtxos(txStreamCtx)
}
return nil
}
func (a *covenantArkClient) InitWithWallet(ctx context.Context, args InitWithWalletArgs) error {
err := a.arkClient.initWithWallet(ctx, args)
if err != nil {
return err
}
if a.WithTransactionFeed {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
a.txStreamCtxCancel = txStreamCtxCancel
go a.listenForTxStream(txStreamCtx)
go a.listenForBoardingUtxos(txStreamCtx)
}
return nil
}
func (a *covenantArkClient) listenForTxStream(ctx context.Context) {
eventChan, closeFunc, err := a.client.GetTransactionsStream(ctx)
if err != nil {
log.WithError(err).Error("Failed to get transaction stream")
return
}
defer closeFunc()
for {
select {
case event, ok := <-eventChan:
if !ok {
return
}
a.processTransactionEvent(event)
case <-ctx.Done():
return
}
}
}
func (a *covenantArkClient) processTransactionEvent(
event client.TransactionEvent,
) {
// TODO considering current covenant state where all payments happening in round
//and that this is going to change we leave this unimplemented until asnc payments are implemented
//also with current state it is not possible to cover some edge cases like when in a round there
//are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
}
func (a *covenantArkClient) listenForBoardingUtxos(
ctx context.Context,
) {
// TODO considering current covenant state where all payments happening in round
//and that this is going to change we leave this unimplemented until asnc payments are implemented
//also with current state it is not possible to cover some edge cases like when in a round there
//are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
}
func (a *covenantArkClient) ListVtxos(
@@ -549,13 +662,19 @@ func (a *covenantArkClient) Claim(ctx context.Context) (string, error) {
)
}
func (a *covenantArkClient) GetTransactionHistory(ctx context.Context) ([]Transaction, error) {
func (a *covenantArkClient) GetTransactionHistory(
ctx context.Context,
) ([]types.Transaction, error) {
if a.Config.WithTransactionFeed {
return a.store.TransactionStore().GetAllTransactions(ctx)
}
spendableVtxos, spentVtxos, err := a.ListVtxos(ctx)
if err != nil {
return nil, err
}
config, err := a.store.GetData(ctx)
config, err := a.store.ConfigStore().GetData(ctx)
if err != nil {
return nil, err
}
@@ -1183,7 +1302,7 @@ func (a *covenantArkClient) validateCongestionTree(
if !utils.IsOnchainOnly(receivers) {
if err := tree.ValidateCongestionTree(
event.Tree, poolTx, a.StoreData.AspPubkey, a.RoundLifetime,
event.Tree, poolTx, a.Config.AspPubkey, a.RoundLifetime,
); err != nil {
return err
}
@@ -1666,7 +1785,9 @@ func (a *covenantArkClient) offchainAddressToDefaultVtxoDescriptor(addr string)
return vtxoScript.ToDescriptor(), nil
}
func (a *covenantArkClient) getBoardingTxs(ctx context.Context) (transactions []Transaction) {
func (a *covenantArkClient) getBoardingTxs(
ctx context.Context,
) (transactions []types.Transaction) {
utxos, err := a.getClaimableBoardingUtxos(ctx)
if err != nil {
return nil
@@ -1683,21 +1804,29 @@ func (a *covenantArkClient) getBoardingTxs(ctx context.Context) (transactions []
}
for _, u := range allUtxos {
transactions = append(transactions, Transaction{
BoardingTxid: u.Txid,
Amount: u.Amount,
Type: TxReceived,
CreatedAt: u.CreatedAt,
pending := false
if isPending[u.Txid] {
pending = true
}
transactions = append(transactions, types.Transaction{
TransactionKey: types.TransactionKey{
BoardingTxid: u.Txid,
},
Amount: u.Amount,
Type: types.TxReceived,
CreatedAt: u.CreatedAt,
IsPending: pending,
})
}
return
}
func vtxosToTxsCovenant(
roundLifetime int64, spendable, spent []client.Vtxo, boardingTxs []Transaction,
) ([]Transaction, error) {
transactions := make([]Transaction, 0)
unconfirmedBoardingTxs := make([]Transaction, 0)
roundLifetime int64, spendable, spent []client.Vtxo, boardingTxs []types.Transaction,
) ([]types.Transaction, error) {
transactions := make([]types.Transaction, 0)
unconfirmedBoardingTxs := make([]types.Transaction, 0)
for _, tx := range boardingTxs {
emptyTime := time.Time{}
if tx.CreatedAt == emptyTime {
@@ -1722,9 +1851,9 @@ func vtxosToTxsCovenant(
}
}
// what kind of tx was this? send or receive?
txType := TxReceived
txType := types.TxReceived
if amount < 0 {
txType = TxSent
txType = types.TxSent
}
// get redeem txid
redeemTxid := ""
@@ -1736,12 +1865,14 @@ func vtxosToTxsCovenant(
redeemTxid = txid
}
// add transaction
transactions = append(transactions, Transaction{
RoundTxid: v.RoundTxid,
RedeemTxid: redeemTxid,
Amount: uint64(math.Abs(float64(amount))),
Type: txType,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
transactions = append(transactions, types.Transaction{
TransactionKey: types.TransactionKey{
RoundTxid: v.RoundTxid,
RedeemTxid: redeemTxid,
},
Amount: uint64(math.Abs(float64(amount))),
Type: txType,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
})
}

View File

@@ -18,7 +18,7 @@ import (
"github.com/ark-network/ark/pkg/client-sdk/explorer"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/redemption"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil"
@@ -57,86 +57,468 @@ type covenantlessArkClient struct {
*arkClient
}
func NewCovenantlessClient(storeSvc store.ConfigStore) (ArkClient, error) {
data, err := storeSvc.GetData(context.Background())
func NewCovenantlessClient(sdkStore types.Store) (ArkClient, error) {
cfgData, err := sdkStore.ConfigStore().GetData(context.Background())
if err != nil {
return nil, err
}
if data != nil {
if cfgData != nil {
return nil, ErrAlreadyInitialized
}
return &covenantlessArkClient{&arkClient{store: storeSvc}}, nil
return &covenantlessArkClient{
&arkClient{
store: sdkStore,
},
}, nil
}
func LoadCovenantlessClient(storeSvc store.ConfigStore) (ArkClient, error) {
if storeSvc == nil {
return nil, fmt.Errorf("missin store service")
func LoadCovenantlessClient(sdkStore types.Store) (ArkClient, error) {
if sdkStore == nil {
return nil, fmt.Errorf("missin sdk repository")
}
data, err := storeSvc.GetData(context.Background())
cfgData, err := sdkStore.ConfigStore().GetData(context.Background())
if err != nil {
return nil, err
}
if data == nil {
if cfgData == nil {
return nil, ErrNotInitialized
}
clientSvc, err := getClient(
supportedClients, data.ClientType, data.AspUrl,
supportedClients, cfgData.ClientType, cfgData.AspUrl,
)
if err != nil {
return nil, fmt.Errorf("failed to setup transport client: %s", err)
}
explorerSvc, err := getExplorer(data.ExplorerURL, data.Network.Name)
explorerSvc, err := getExplorer(cfgData.ExplorerURL, cfgData.Network.Name)
if err != nil {
return nil, fmt.Errorf("failed to setup explorer: %s", err)
}
walletSvc, err := getWallet(storeSvc, data, supportedWallets)
walletSvc, err := getWallet(
sdkStore.ConfigStore(),
cfgData,
supportedWallets,
)
if err != nil {
return nil, fmt.Errorf("faile to setup wallet: %s", err)
}
return &covenantlessArkClient{
&arkClient{data, walletSvc, storeSvc, explorerSvc, clientSvc},
}, nil
covenantlessClient := covenantlessArkClient{
&arkClient{
Config: cfgData,
wallet: walletSvc,
store: sdkStore,
explorer: explorerSvc,
client: clientSvc,
},
}
if cfgData.WithTransactionFeed {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
covenantlessClient.txStreamCtxCancel = txStreamCtxCancel
go covenantlessClient.listenForTransactions(txStreamCtx)
go covenantlessClient.listenForBoardingUtxos(txStreamCtx)
}
return &covenantlessClient, nil
}
func LoadCovenantlessClientWithWallet(
storeSvc store.ConfigStore, walletSvc wallet.WalletService,
sdkStore types.Store, walletSvc wallet.WalletService,
) (ArkClient, error) {
if storeSvc == nil {
return nil, fmt.Errorf("missin store service")
if sdkStore == nil {
return nil, fmt.Errorf("missin sdk repository")
}
if walletSvc == nil {
return nil, fmt.Errorf("missin wallet service")
}
data, err := storeSvc.GetData(context.Background())
cfgData, err := sdkStore.ConfigStore().GetData(context.Background())
if err != nil {
return nil, err
}
if data == nil {
if cfgData == nil {
return nil, ErrNotInitialized
}
clientSvc, err := getClient(
supportedClients, data.ClientType, data.AspUrl,
supportedClients, cfgData.ClientType, cfgData.AspUrl,
)
if err != nil {
return nil, fmt.Errorf("failed to setup transport client: %s", err)
}
explorerSvc, err := getExplorer(data.ExplorerURL, data.Network.Name)
explorerSvc, err := getExplorer(cfgData.ExplorerURL, cfgData.Network.Name)
if err != nil {
return nil, fmt.Errorf("failed to setup explorer: %s", err)
}
return &covenantlessArkClient{
&arkClient{data, walletSvc, storeSvc, explorerSvc, clientSvc},
}, nil
covenantlessClient := covenantlessArkClient{
&arkClient{
Config: cfgData,
wallet: walletSvc,
store: sdkStore,
explorer: explorerSvc,
client: clientSvc,
},
}
if cfgData.WithTransactionFeed {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
covenantlessClient.txStreamCtxCancel = txStreamCtxCancel
go covenantlessClient.listenForTransactions(txStreamCtx)
go covenantlessClient.listenForBoardingUtxos(txStreamCtx)
}
return &covenantlessClient, nil
}
func (a *covenantlessArkClient) Init(ctx context.Context, args InitArgs) error {
if err := a.arkClient.init(ctx, args); err != nil {
return err
}
if args.ListenTransactionStream {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
a.txStreamCtxCancel = txStreamCtxCancel
go a.listenForTransactions(txStreamCtx)
go a.listenForBoardingUtxos(txStreamCtx)
}
return nil
}
func (a *covenantlessArkClient) InitWithWallet(ctx context.Context, args InitWithWalletArgs) error {
if err := a.arkClient.initWithWallet(ctx, args); err != nil {
return err
}
if a.WithTransactionFeed {
txStreamCtx, txStreamCtxCancel := context.WithCancel(context.Background())
a.txStreamCtxCancel = txStreamCtxCancel
go a.listenForTransactions(txStreamCtx)
go a.listenForBoardingUtxos(txStreamCtx)
}
return nil
}
func (a *covenantlessArkClient) listenForTransactions(ctx context.Context) {
eventChan, closeFunc, err := a.client.GetTransactionsStream(ctx)
if err != nil {
log.WithError(err).Error("Failed to get transaction stream")
return
}
defer closeFunc()
offchainAddr, _, err := a.wallet.NewAddress(ctx, true)
if err != nil {
log.WithError(err).Error("Failed to get new address")
return
}
desc, err := a.offchainAddressToDefaultVtxoDescriptor(offchainAddr)
if err != nil {
log.WithError(err).Error("Failed to get descriptor for new address")
return
}
for {
select {
case event, ok := <-eventChan:
if !ok {
continue
}
if event.Err != nil {
log.WithError(event.Err).Error("Error in transaction stream")
continue
}
pendingBoardingTxsMap, newPendingBoardingTxs, err := a.getBoardingPendingTransactions(ctx)
if err != nil {
log.WithError(err).Error("Failed to get pending transactions")
continue
}
if err := a.store.TransactionStore().
AddTransactions(ctx, newPendingBoardingTxs); err != nil {
log.WithError(err).Error("Failed to insert new boarding transactions")
continue
}
a.processTransactionEvent(desc, event, pendingBoardingTxsMap)
case <-ctx.Done():
return
}
}
}
func (a *covenantlessArkClient) listenForBoardingUtxos(ctx context.Context) {
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
_, newPendingBoardingTxs, err := a.getBoardingPendingTransactions(ctx)
if err != nil {
log.WithError(err).Error("Failed to get pending transactions")
continue
}
if err := a.store.TransactionStore().
AddTransactions(ctx, newPendingBoardingTxs); err != nil {
log.WithError(err).Error("Failed to insert new boarding transactions")
continue
}
case <-ctx.Done():
return
}
}
}
func (a *covenantlessArkClient) getBoardingPendingTransactions(
ctx context.Context,
) (map[string]types.Transaction, []types.Transaction, error) {
oldTxs, err := a.store.TransactionStore().GetAllTransactions(ctx)
if err != nil {
return nil, nil, err
}
pendingBoardingTxsMap := make(map[string]types.Transaction)
for _, tx := range oldTxs {
if tx.IsBoarding() {
if tx.IsPending {
pendingBoardingTxsMap[tx.BoardingTxid] = tx
}
}
}
boardingTxs, _, err := a.getBoardingTxs(ctx)
if err != nil {
return nil, nil, err
}
newPendingBoardingTxs := make([]types.Transaction, 0)
for _, tx := range boardingTxs {
if tx.IsBoarding() && tx.IsPending {
if _, ok := pendingBoardingTxsMap[tx.BoardingTxid]; !ok {
newPendingBoardingTxs = append(newPendingBoardingTxs, tx)
pendingBoardingTxsMap[tx.BoardingTxid] = tx
}
}
}
return pendingBoardingTxsMap, newPendingBoardingTxs, nil
}
func (a *covenantlessArkClient) processTransactionEvent(
descriptor string,
event client.TransactionEvent,
pendingBoardingTxsMap map[string]types.Transaction,
) {
if event.Round != nil {
boardingAmount := 0
boardingTxsToUpdate := make([]types.Transaction, 0)
for _, v := range event.Round.ClaimedBoardingUtxos {
boardingKey := fmt.Sprintf("%v-%v", v.Txid, v.VOut)
if tx, ok := pendingBoardingTxsMap[boardingKey]; ok {
boardingAmount += int(tx.Amount)
tx.IsPending = false
boardingTxsToUpdate = append(boardingTxsToUpdate, tx)
}
}
if err := a.store.TransactionStore().
UpdateTransactions(context.Background(), boardingTxsToUpdate); err != nil {
log.WithError(err).Error("Failed to update boarding transactions")
}
spentKeys := make([]types.VtxoKey, 0, len(event.Round.SpentVtxos))
for _, v := range event.Round.SpentVtxos {
spentKeys = append(spentKeys, types.VtxoKey{
Txid: v.Txid,
VOut: v.VOut,
})
}
vtxos, err := a.store.VtxoStore().
GetVtxos(context.Background(), spentKeys)
if err != nil {
log.WithError(err).Error("Failed to get spent vtxos")
return
}
if len(vtxos) > 0 {
vtxosToUpdate := make([]types.Vtxo, 0)
for _, v := range vtxos {
v.Spent = true
v.Pending = false
vtxosToUpdate = append(vtxosToUpdate, v)
}
if err := a.store.VtxoStore().
UpdateVtxos(context.Background(), vtxosToUpdate); err != nil {
log.WithError(err).Error("Failed to update spent vtxos")
}
}
vtxosToInsert := make([]types.Vtxo, 0)
txsToInsert := make([]types.Transaction, 0)
for _, v := range event.Round.SpendableVtxos {
if v.Descriptor == descriptor {
vtxosToInsert = append(vtxosToInsert, types.Vtxo{
VtxoKey: types.VtxoKey{
Txid: v.Txid,
VOut: v.VOut,
},
Amount: v.Amount,
ExpiresAt: v.ExpiresAt,
RedeemTx: event.Round.Txid,
Pending: false,
SpentBy: v.SpentBy,
Spent: false,
})
if boardingAmount == int(v.Amount) {
continue
}
txsToInsert = append(txsToInsert, types.Transaction{
TransactionKey: types.TransactionKey{
RoundTxid: event.Round.Txid,
},
Amount: v.Amount,
Type: types.TxReceived,
CreatedAt: time.Now(), //TODO is this ok?
})
}
}
if err := a.store.VtxoStore().
AddVtxos(context.Background(), vtxosToInsert); err != nil {
log.WithError(err).Error("Failed to insert new vtxos")
return
}
if err := a.store.TransactionStore().
AddTransactions(context.Background(), txsToInsert); err != nil {
log.WithError(err).Error("Failed to insert received transaction")
return
}
}
if event.Redeem != nil {
vtxosToInsert := make([]types.Vtxo, 0)
spentKeys := make([]types.VtxoKey, 0, len(event.Redeem.SpentVtxos))
for _, v := range event.Redeem.SpentVtxos {
spentKeys = append(spentKeys, types.VtxoKey{
Txid: v.Txid,
VOut: v.VOut,
})
}
vtxos, err := a.store.VtxoStore().
GetVtxos(context.Background(), spentKeys)
if err != nil {
log.WithError(err).Error("Failed to get spent vtxos")
return
}
if len(vtxos) > 0 {
inputAmount := uint64(0)
vtxosToUpdate := make([]types.Vtxo, 0)
for _, v := range vtxos {
v.Spent = true
vtxosToUpdate = append(vtxosToUpdate, v)
inputAmount += v.Amount
}
if err := a.store.VtxoStore().
UpdateVtxos(context.Background(), vtxosToUpdate); err != nil {
log.WithError(err).Error("Failed to update spent vtxos")
return
}
outputAmount := uint64(0)
for _, v := range event.Redeem.SpendableVtxos {
if v.Descriptor == descriptor {
vtxosToInsert = append(vtxosToInsert, types.Vtxo{
VtxoKey: types.VtxoKey{
Txid: v.Txid,
VOut: v.VOut,
},
Amount: v.Amount,
ExpiresAt: v.ExpiresAt,
RedeemTx: event.Redeem.Txid,
Pending: true,
SpentBy: v.SpentBy,
Spent: false,
})
outputAmount += v.Amount
}
}
tx := types.Transaction{
TransactionKey: types.TransactionKey{
RedeemTxid: event.Redeem.Txid,
},
Amount: inputAmount - outputAmount,
Type: types.TxSent,
IsPending: true,
CreatedAt: time.Now(), //TODO is this ok?
}
if err := a.store.TransactionStore().
AddTransactions(context.Background(), []types.Transaction{tx}); err != nil {
log.WithError(err).Error("Failed to insert received transaction")
}
} else {
for _, v := range event.Redeem.SpendableVtxos {
if v.Descriptor == descriptor {
vtxosToInsert = append(vtxosToInsert, types.Vtxo{
VtxoKey: types.VtxoKey{
Txid: v.Txid,
VOut: v.VOut,
},
Amount: v.Amount,
ExpiresAt: v.ExpiresAt,
RedeemTx: event.Redeem.Txid,
Pending: true,
SpentBy: v.SpentBy,
Spent: false,
})
tx := types.Transaction{
TransactionKey: types.TransactionKey{
RedeemTxid: event.Redeem.Txid,
},
Amount: v.Amount,
Type: types.TxReceived,
IsPending: true,
CreatedAt: time.Now(), //TODO is this ok?
}
if err := a.store.TransactionStore().
AddTransactions(context.Background(), []types.Transaction{tx}); err != nil {
log.WithError(err).Error("Failed to insert received transaction")
}
}
}
}
if err := a.store.VtxoStore().
AddVtxos(context.Background(), vtxosToInsert); err != nil {
log.WithError(err).Error("Failed to insert new vtxos")
return
}
}
}
func (a *covenantlessArkClient) ListVtxos(
@@ -725,8 +1107,14 @@ func (a *covenantlessArkClient) Claim(ctx context.Context) (string, error) {
)
}
func (a *covenantlessArkClient) GetTransactionHistory(ctx context.Context) ([]Transaction, error) {
if a.StoreData == nil {
func (a *covenantlessArkClient) GetTransactionHistory(
ctx context.Context,
) ([]types.Transaction, error) {
if a.Config.WithTransactionFeed {
return a.store.TransactionStore().GetAllTransactions(ctx)
}
if a.Config == nil {
return nil, fmt.Errorf("client not initialized")
}
@@ -741,7 +1129,7 @@ func (a *covenantlessArkClient) GetTransactionHistory(ctx context.Context) ([]Tr
}
offchainTxs, err := vtxosToTxsCovenantless(
a.StoreData.RoundLifetime, spendableVtxos, spentVtxos, ignoreVtxos,
a.Config.RoundLifetime, spendableVtxos, spentVtxos, ignoreVtxos,
)
if err != nil {
return nil, err
@@ -1401,7 +1789,7 @@ func (a *covenantlessArkClient) validateCongestionTree(
if !utils.IsOnchainOnly(receivers) {
if err := bitcointree.ValidateCongestionTree(
event.Tree, poolTx, a.StoreData.AspPubkey, a.RoundLifetime,
event.Tree, poolTx, a.Config.AspPubkey, a.RoundLifetime,
); err != nil {
return err
}
@@ -2061,7 +2449,7 @@ func (a *covenantlessArkClient) offchainAddressToDefaultVtxoDescriptor(addr stri
// offchain tx history and prevent duplicates.
func (a *covenantlessArkClient) getBoardingTxs(
ctx context.Context,
) ([]Transaction, map[string]struct{}, error) {
) ([]types.Transaction, map[string]struct{}, error) {
utxos, err := a.getClaimableBoardingUtxos(ctx)
if err != nil {
return nil, nil, err
@@ -2077,20 +2465,22 @@ func (a *covenantlessArkClient) getBoardingTxs(
return nil, nil, err
}
unconfirmedTxs := make([]Transaction, 0)
confirmedTxs := make([]Transaction, 0)
unconfirmedTxs := make([]types.Transaction, 0)
confirmedTxs := make([]types.Transaction, 0)
for _, u := range allUtxos {
pending := false
if isPending[u.Txid] {
pending = true
}
tx := Transaction{
BoardingTxid: u.Txid,
Amount: u.Amount,
Type: TxReceived,
IsPending: pending,
CreatedAt: u.CreatedAt,
tx := types.Transaction{
TransactionKey: types.TransactionKey{
BoardingTxid: u.Txid,
},
Amount: u.Amount,
Type: types.TxReceived,
IsPending: pending,
CreatedAt: u.CreatedAt,
}
emptyTime := time.Time{}
@@ -2116,19 +2506,21 @@ func findVtxosBySpentBy(allVtxos []client.Vtxo, txid string) (vtxos []client.Vtx
func vtxosToTxsCovenantless(
roundLifetime int64, spendable, spent []client.Vtxo, ignoreVtxos map[string]struct{},
) ([]Transaction, error) {
transactions := make([]Transaction, 0)
) ([]types.Transaction, error) {
transactions := make([]types.Transaction, 0)
indexedTxs := make(map[string]Transaction)
indexedTxs := make(map[string]types.Transaction)
for _, v := range spent {
// If the vtxo was pending and is spent => it's been claimed.
if v.Pending {
transactions = append(transactions, Transaction{
RedeemTxid: v.Txid,
Amount: v.Amount,
Type: TxReceived,
IsPending: false,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
transactions = append(transactions, types.Transaction{
TransactionKey: types.TransactionKey{
RedeemTxid: v.Txid,
},
Amount: v.Amount,
Type: types.TxReceived,
IsPending: false,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
})
// Delete any duplicate in the indexed list.
delete(indexedTxs, v.SpentBy)
@@ -2151,13 +2543,15 @@ func vtxosToTxsCovenantless(
// Add a transaction to the indexed list if not existing, it will be deleted if it's a duplicate.
tx, ok := indexedTxs[v.SpentBy]
if !ok {
indexedTxs[v.SpentBy] = Transaction{
RedeemTxid: v.SpentBy,
RoundTxid: v.SpentBy,
Amount: v.Amount,
Type: TxSent,
IsPending: false,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
indexedTxs[v.SpentBy] = types.Transaction{
TransactionKey: types.TransactionKey{
RedeemTxid: v.SpentBy,
RoundTxid: v.SpentBy,
},
Amount: v.Amount,
Type: types.TxSent,
IsPending: false,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
}
continue
}
@@ -2184,13 +2578,15 @@ func vtxosToTxsCovenantless(
if v.RoundTxid == "" {
redeemTxid = v.Txid
}
transactions = append(transactions, Transaction{
RedeemTxid: redeemTxid,
RoundTxid: v.RoundTxid,
Amount: v.Amount,
Type: TxReceived,
IsPending: v.Pending,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
transactions = append(transactions, types.Transaction{
TransactionKey: types.TransactionKey{
RedeemTxid: redeemTxid,
RoundTxid: v.RoundTxid,
},
Amount: v.Amount,
Type: types.TxReceived,
IsPending: v.Pending,
CreatedAt: getCreatedAtFromExpiry(roundLifetime, *v.ExpiresAt),
})
continue
}

View File

@@ -5,12 +5,15 @@ import (
"fmt"
"io"
"os/exec"
"path"
"strings"
"sync"
"time"
"github.com/ark-network/ark/common"
arksdk "github.com/ark-network/ark/pkg/client-sdk"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
log "github.com/sirupsen/logrus"
)
@@ -26,7 +29,7 @@ func main() {
log.Info("alice is setting up her ark wallet...")
aliceArkClient, err := setupArkClient()
aliceArkClient, err := setupArkClient("alice")
if err != nil {
log.Fatal(err)
}
@@ -70,7 +73,7 @@ func main() {
fmt.Println("")
log.Info("bob is setting up his ark wallet...")
bobArkClient, err := setupArkClient()
bobArkClient, err := setupArkClient("bob")
if err != nil {
log.Fatal(err)
}
@@ -133,12 +136,18 @@ func main() {
log.Infof("bob offchain balance: %d", bobBalance.OffchainBalance.Total)
}
func setupArkClient() (arksdk.ArkClient, error) {
storeSvc, err := inmemorystore.NewConfigStore()
func setupArkClient(wallet string) (arksdk.ArkClient, error) {
dbDir := common.AppDataDir(path.Join("ark-example", wallet), false)
appDataStore, err := store.NewStore(store.Config{
ConfigStoreType: types.FileStore,
AppDataStoreType: types.KVStore,
BaseDir: dbDir,
})
if err != nil {
return nil, fmt.Errorf("failed to setup store: %s", err)
return nil, fmt.Errorf("failed to setup app data store: %s", err)
}
client, err := arksdk.NewCovenantClient(storeSvc)
client, err := arksdk.NewCovenantClient(appDataStore)
if err != nil {
return nil, fmt.Errorf("failed to setup ark client: %s", err)
}

View File

@@ -19,10 +19,11 @@
async function initWallet() {
try {
const chain = "liquid";
const walletType = "singlekey"
const clientType = "rest"
const walletType = "singlekey";
const clientType = "rest";
const privateKey = document.getElementById("prvkey").value;
const password = document.getElementById("i_password").value;
const explorerUrl = "";
if (!password) {
logMessage("Init error: password is required");
return;
@@ -32,7 +33,7 @@
logMessage("Init error: asp url is required");
return;
}
await init(walletType, clientType, aspUrl, privateKey, password, chain);
await init(walletType, clientType, aspUrl, privateKey, password, chain, explorerUrl);
logMessage("wallet initialized and connected to ASP");
await config();
} catch (err) {

View File

@@ -5,12 +5,15 @@ import (
"fmt"
"io"
"os/exec"
"path"
"strings"
"sync"
"time"
"github.com/ark-network/ark/common"
arksdk "github.com/ark-network/ark/pkg/client-sdk"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
log "github.com/sirupsen/logrus"
)
@@ -22,15 +25,36 @@ var (
)
func main() {
ctx := context.Background()
var (
ctx = context.Background()
err error
aliceArkClient arksdk.ArkClient
bobArkClient arksdk.ArkClient
)
defer func() {
if aliceArkClient != nil {
if err := bobArkClient.Stop(); err != nil {
log.Error(err)
}
}
if bobArkClient != nil {
if err := aliceArkClient.Stop(); err != nil {
log.Error(err)
}
}
}()
log.Info("alice is setting up her ark wallet...")
aliceArkClient, err := setupArkClient()
aliceArkClient, err = setupArkClient("alice")
if err != nil {
log.Fatal(err)
}
logTxEvents("alice", aliceArkClient)
if err := aliceArkClient.Unlock(ctx, password); err != nil {
log.Fatal(err)
}
@@ -70,11 +94,13 @@ func main() {
fmt.Println("")
log.Info("bob is setting up his ark wallet...")
bobArkClient, err := setupArkClient()
bobArkClient, err = setupArkClient("bob")
if err != nil {
log.Fatal(err)
}
logTxEvents("bob", bobArkClient)
if err := bobArkClient.Unlock(ctx, password); err != nil {
log.Fatal(err)
}
@@ -139,23 +165,32 @@ func main() {
}
log.Infof("bob claimed the incoming payment in round %s", roundTxid)
time.Sleep(500 * time.Second)
}
func setupArkClient() (arksdk.ArkClient, error) {
storeSvc, err := inmemorystore.NewConfigStore()
func setupArkClient(wallet string) (arksdk.ArkClient, error) {
dbDir := common.AppDataDir(path.Join("ark-example", wallet), false)
appDataStore, err := store.NewStore(store.Config{
ConfigStoreType: types.FileStore,
AppDataStoreType: types.KVStore,
BaseDir: dbDir,
})
if err != nil {
return nil, fmt.Errorf("failed to setup store: %s", err)
return nil, fmt.Errorf("failed to setup app data store: %s", err)
}
client, err := arksdk.NewCovenantlessClient(storeSvc)
client, err := arksdk.NewCovenantlessClient(appDataStore)
if err != nil {
return nil, fmt.Errorf("failed to setup ark client: %s", err)
}
if err := client.Init(context.Background(), arksdk.InitArgs{
WalletType: walletType,
ClientType: clientType,
AspUrl: aspUrl,
Password: password,
WalletType: walletType,
ClientType: clientType,
AspUrl: aspUrl,
Password: password,
ListenTransactionStream: true,
}); err != nil {
return nil, fmt.Errorf("failed to initialize wallet: %s", err)
}
@@ -233,3 +268,17 @@ func generateBlock() error {
time.Sleep(6 * time.Second)
return nil
}
func logTxEvents(wallet string, client arksdk.ArkClient) {
txsChan := client.GetTransactionEventChannel()
go func() {
for txEvent := range txsChan {
msg := fmt.Sprintf("[EVENT]%s: tx event: %s, %d", wallet, txEvent.Event, txEvent.Tx.Amount)
if txEvent.Tx.IsBoarding() {
msg += fmt.Sprintf(", boarding tx: %s", txEvent.Tx.BoardingTxid)
}
log.Infoln(msg)
}
}()
log.Infof("%s tx event listener started", wallet)
}

View File

@@ -19,10 +19,11 @@
async function initWallet() {
try {
const chain = "bitcoin";
const walletType = "singlekey"
const clientType = "rest"
const walletType = "singlekey";
const clientType = "rest";
const privateKey = document.getElementById("prvkey").value;
const password = document.getElementById("i_password").value;
const explorerUrl = "";
if (!password) {
logMessage("Init error: password is required");
return;
@@ -32,7 +33,7 @@
logMessage("Init error: asp url is required");
return;
}
await init(walletType, clientType, aspUrl, privateKey, password, chain);
await init(walletType, clientType, aspUrl, privateKey, password, chain, explorerUrl);
logMessage("wallet initialized and connected to ASP");
await config();
} catch (err) {
@@ -80,7 +81,7 @@
const amount = parseInt(amountStr, 10);
await unlock(password);
const txID = await sendOffChain(false, [{ To: address, Amount: amount }]);
const txID = await sendAsync(false, [{ To: address, Amount: amount }]);
logMessage("Sent money with tx ID: " + txID);
} catch (err) {
logMessage("Send error: " + err.message);

View File

@@ -11,6 +11,7 @@ require (
github.com/btcsuite/btcd/btcutil/psbt v1.1.9
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
github.com/dgraph-io/badger/v4 v4.2.0
github.com/go-openapi/errors v0.22.0
github.com/go-openapi/runtime v0.28.0
github.com/go-openapi/strfmt v0.23.0
@@ -19,6 +20,7 @@ require (
github.com/lightningnetwork/lnd v0.18.2-beta
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/timshannon/badgerhold/v4 v4.0.3
github.com/vulpemventures/go-elements v0.5.4
golang.org/x/crypto v0.26.0
google.golang.org/grpc v1.65.0
@@ -31,9 +33,12 @@ require (
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
github.com/btcsuite/winsvc v1.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/lru v1.1.3 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
@@ -42,25 +47,33 @@ require (
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/loads v0.22.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/flatbuffers v24.3.25+incompatible // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/jessevdk/go-flags v1.6.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jrick/logrotate v1.0.0 // indirect
github.com/kkdai/bstream v1.0.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/lightningnetwork/lnd/fn v1.2.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.30.0 // indirect
go.opentelemetry.io/otel/metric v1.30.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect

View File

@@ -1,5 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
@@ -31,6 +34,18 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
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.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -45,9 +60,24 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/decred/dcrd/lru v1.1.3 h1:w9EAbvGLyzm6jTjF83UKuqZEiUtJmvRhQDOCEIvSuE0=
github.com/decred/dcrd/lru v1.1.3/go.mod h1:Tw0i0pJyiLEx/oZdHLe1Wdv/Y7EGzAX+sYftnmxBR4o=
github.com/dgraph-io/badger/v4 v4.1.0/go.mod h1:P50u28d39ibBRmIJuQC/NSdBOg46HnHw7al2SW5QRHg=
github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs=
github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
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.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -73,26 +103,58 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4=
github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/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.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v23.5.9+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI=
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
@@ -101,23 +163,36 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8=
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lightningnetwork/lnd v0.18.2-beta h1:Qv4xQ2ka05vqzmdkFdISHCHP6CzHoYNVKfD18XPjHsM=
github.com/lightningnetwork/lnd v0.18.2-beta/go.mod h1:cGQR1cVEZFZQcCx2VBbDY8xwGjCz+SupSopU1HpjP2I=
github.com/lightningnetwork/lnd/fn v1.2.1 h1:pPsVGrwi9QBwdLJzaEGK33wmiVKOxs/zc8H7+MamFf0=
github.com/lightningnetwork/lnd/fn v1.2.1/go.mod h1:SyFohpVrARPKH3XVAJZlXdVe+IwMYc4OMAvrDY32kw0=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -125,84 +200,187 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/timshannon/badgerhold/v4 v4.0.3 h1:W6pd2qckoXw2cl8eH0ZCV/9CXNaXvaM26tzFi5Tj+v8=
github.com/timshannon/badgerhold/v4 v4.0.3/go.mod h1:IkZIr0kcZLMdD7YJfW/G6epb6ZXHD/h0XR2BTk/VZg8=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 h1:CTcw80hz/Sw8hqlKX5ZYvBUF5gAHSHwdjXxRf/cjDcI=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:GXBJykxW2kUcktGdsgyay7uwwWvkljASfljNcT0mbh8=
github.com/vulpemventures/go-elements v0.5.4 h1:l94xoa9aYPPWiOB7Pmi08rKYvdk/n/sQIbLkQfEAASc=
github.com/vulpemventures/go-elements v0.5.4/go.mod h1:Tvhb+rZWv3lxoI5CdK03J3V+e2QVr/7UAnCYILxFSq4=
github.com/vulpemventures/go-secp256k1-zkp v1.1.6 h1:BmsrmXRLUibwa75Qkk8yELjpzCzlAjYFGLiLiOdq7Xo=
github.com/vulpemventures/go-secp256k1-zkp v1.1.6/go.mod h1:zo7CpgkuPgoe7fAV+inyxsI9IhGmcoFgyD8nqZaPSOM=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20181205085412-a5c9d58dba9a/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 h1:V71AcdLZr2p8dC9dbOIMCpqi4EmRl8wUwnJzXXLmbmc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -210,18 +388,28 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -0,0 +1,142 @@
package filestore
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strconv"
"github.com/ark-network/ark/pkg/client-sdk/types"
)
const (
configStoreFilename = "state.json"
)
type configStore struct {
filePath string
}
func NewConfigStore(baseDir string) (types.ConfigStore, error) {
if len(baseDir) <= 0 {
return nil, fmt.Errorf("missing base directory")
}
datadir := cleanAndExpandPath(baseDir)
if err := makeDirectoryIfNotExists(datadir); err != nil {
return nil, fmt.Errorf("failed to initialize datadir: %s", err)
}
filePath := filepath.Join(datadir, configStoreFilename)
store := &configStore{filePath}
if _, err := store.open(); err != nil {
return nil, fmt.Errorf("failed to open store: %s", err)
}
return store, nil
}
func (s *configStore) Close() {}
func (s *configStore) GetType() string {
return "file"
}
func (s *configStore) GetDatadir() string {
return filepath.Dir(s.filePath)
}
func (s *configStore) AddData(ctx context.Context, data types.Config) error {
sd := &storeData{
AspUrl: data.AspUrl,
AspPubkey: hex.EncodeToString(data.AspPubkey.SerializeCompressed()),
WalletType: data.WalletType,
ClientType: data.ClientType,
Network: data.Network.Name,
RoundLifetime: fmt.Sprintf("%d", data.RoundLifetime),
RoundInterval: fmt.Sprintf("%d", data.RoundInterval),
UnilateralExitDelay: fmt.Sprintf("%d", data.UnilateralExitDelay),
Dust: fmt.Sprintf("%d", data.Dust),
BoardingDescriptorTemplate: data.BoardingDescriptorTemplate,
ExplorerURL: data.ExplorerURL,
ForfeitAddress: data.ForfeitAddress,
WithTransactionFeed: strconv.FormatBool(data.WithTransactionFeed),
}
if err := s.write(sd); err != nil {
return fmt.Errorf("failed to write to store: %s", err)
}
return nil
}
func (s *configStore) GetData(_ context.Context) (*types.Config, error) {
sd, err := s.open()
if err != nil {
return nil, err
}
if sd.isEmpty() {
return nil, nil
}
data := sd.decode()
return &data, nil
}
func (s *configStore) CleanData(ctx context.Context) error {
if err := s.write(&storeData{}); err != nil {
return fmt.Errorf("failed to write to store: %s", err)
}
return nil
}
func (s *configStore) open() (*storeData, error) {
file, err := os.ReadFile(s.filePath)
if err != nil {
if !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to open store: %s", err)
}
if err := s.write(&storeData{}); err != nil {
return nil, fmt.Errorf("failed to initialize store: %s", err)
}
return nil, nil
}
data := &storeData{}
if err := json.Unmarshal(file, data); err != nil {
return nil, fmt.Errorf("failed to read file store: %s", err)
}
return data, nil
}
func (s *configStore) write(data *storeData) error {
file, err := os.ReadFile(s.filePath)
if err != nil {
if !os.IsNotExist(err) {
return err
}
}
currentData := map[string]string{}
if len(file) > 0 {
if err := json.Unmarshal(file, &currentData); err != nil {
return fmt.Errorf("failed to read file store: %s", err)
}
}
mergedData := merge(currentData, data.asMap())
jsonString, err := json.Marshal(mergedData)
if err != nil {
return err
}
err = os.WriteFile(s.filePath, jsonString, 0755)
if err != nil {
return err
}
return nil
}

View File

@@ -1,239 +0,0 @@
package filestore
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"os/user"
"path/filepath"
"strconv"
"strings"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
const (
filename = "state.json"
)
type storeData struct {
AspUrl string `json:"asp_url"`
AspPubkey string `json:"asp_pubkey"`
WalletType string `json:"wallet_type"`
ClientType string `json:"client_type"`
Network string `json:"network"`
RoundLifetime string `json:"round_lifetime"`
RoundInterval string `json:"round_interval"`
UnilateralExitDelay string `json:"unilateral_exit_delay"`
Dust string `json:"dust"`
BoardingDescriptorTemplate string `json:"boarding_descriptor_template"`
ExplorerURL string `json:"explorer_url"`
ForfeitAddress string `json:"forfeit_address"`
}
func (d storeData) isEmpty() bool {
return d == storeData{}
}
func (d storeData) decode() store.StoreData {
network := utils.NetworkFromString(d.Network)
roundLifetime, _ := strconv.Atoi(d.RoundLifetime)
roundInterval, _ := strconv.Atoi(d.RoundInterval)
unilateralExitDelay, _ := strconv.Atoi(d.UnilateralExitDelay)
dust, _ := strconv.Atoi(d.Dust)
buf, _ := hex.DecodeString(d.AspPubkey)
aspPubkey, _ := secp256k1.ParsePubKey(buf)
explorerURL := d.ExplorerURL
return store.StoreData{
AspUrl: d.AspUrl,
AspPubkey: aspPubkey,
WalletType: d.WalletType,
ClientType: d.ClientType,
Network: network,
RoundLifetime: int64(roundLifetime),
UnilateralExitDelay: int64(unilateralExitDelay),
RoundInterval: int64(roundInterval),
Dust: uint64(dust),
BoardingDescriptorTemplate: d.BoardingDescriptorTemplate,
ExplorerURL: explorerURL,
ForfeitAddress: d.ForfeitAddress,
}
}
func (d storeData) asMap() map[string]string {
return map[string]string{
"asp_url": d.AspUrl,
"asp_pubkey": d.AspPubkey,
"wallet_type": d.WalletType,
"client_type": d.ClientType,
"network": d.Network,
"round_lifetime": d.RoundLifetime,
"round_interval": d.RoundInterval,
"unilateral_exit_delay": d.UnilateralExitDelay,
"dust": d.Dust,
"boarding_descriptor_template": d.BoardingDescriptorTemplate,
"explorer_url": d.ExplorerURL,
"forfeit_address": d.ForfeitAddress,
}
}
type Store struct {
filePath string
}
func NewConfigStore(baseDir string) (store.ConfigStore, error) {
if len(baseDir) <= 0 {
return nil, fmt.Errorf("missing base directory")
}
datadir := cleanAndExpandPath(baseDir)
if err := makeDirectoryIfNotExists(datadir); err != nil {
return nil, fmt.Errorf("failed to initialize datadir: %s", err)
}
filePath := filepath.Join(datadir, filename)
fileStore := &Store{filePath}
if _, err := fileStore.open(); err != nil {
return nil, fmt.Errorf("failed to open store: %s", err)
}
return fileStore, nil
}
func (s *Store) GetType() string {
return store.FileStore
}
func (s *Store) GetDatadir() string {
return filepath.Dir(s.filePath)
}
func (s *Store) AddData(ctx context.Context, data store.StoreData) error {
sd := &storeData{
AspUrl: data.AspUrl,
AspPubkey: hex.EncodeToString(data.AspPubkey.SerializeCompressed()),
WalletType: data.WalletType,
ClientType: data.ClientType,
Network: data.Network.Name,
RoundLifetime: fmt.Sprintf("%d", data.RoundLifetime),
RoundInterval: fmt.Sprintf("%d", data.RoundInterval),
UnilateralExitDelay: fmt.Sprintf("%d", data.UnilateralExitDelay),
Dust: fmt.Sprintf("%d", data.Dust),
BoardingDescriptorTemplate: data.BoardingDescriptorTemplate,
ExplorerURL: data.ExplorerURL,
ForfeitAddress: data.ForfeitAddress,
}
if err := s.write(sd); err != nil {
return fmt.Errorf("failed to write to store: %s", err)
}
return nil
}
func (s *Store) GetData(_ context.Context) (*store.StoreData, error) {
sd, err := s.open()
if err != nil {
return nil, err
}
if sd.isEmpty() {
return nil, nil
}
data := sd.decode()
return &data, nil
}
func (s *Store) CleanData(ctx context.Context) error {
if err := s.write(&storeData{}); err != nil {
return fmt.Errorf("failed to write to store: %s", err)
}
return nil
}
func (s *Store) open() (*storeData, error) {
file, err := os.ReadFile(s.filePath)
if err != nil {
if !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to open store: %s", err)
}
if err := s.write(&storeData{}); err != nil {
return nil, fmt.Errorf("failed to initialize store: %s", err)
}
return nil, nil
}
data := &storeData{}
if err := json.Unmarshal(file, data); err != nil {
return nil, fmt.Errorf("failed to read file store: %s", err)
}
return data, nil
}
func (s *Store) write(data *storeData) error {
file, err := os.ReadFile(s.filePath)
if err != nil {
if !os.IsNotExist(err) {
return err
}
}
currentData := map[string]string{}
if len(file) > 0 {
if err := json.Unmarshal(file, &currentData); err != nil {
return fmt.Errorf("failed to read file store: %s", err)
}
}
mergedData := merge(currentData, data.asMap())
jsonString, err := json.Marshal(mergedData)
if err != nil {
return err
}
err = os.WriteFile(s.filePath, jsonString, 0755)
if err != nil {
return err
}
return nil
}
func cleanAndExpandPath(path string) string {
// Expand initial ~ to OS specific home directory.
if strings.HasPrefix(path, "~") {
var homeDir string
u, err := user.Current()
if err == nil {
homeDir = u.HomeDir
} else {
homeDir = os.Getenv("HOME")
}
path = strings.Replace(path, "~", homeDir, 1)
}
// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
// but the variables can still be expanded via POSIX-style $VARIABLE.
return filepath.Clean(os.ExpandEnv(path))
}
func makeDirectoryIfNotExists(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
return os.MkdirAll(path, os.ModeDir|0755)
}
return nil
}
func merge(maps ...map[string]string) map[string]string {
merge := make(map[string]string, 0)
for _, m := range maps {
for k, v := range m {
merge[k] = v
}
}
return merge
}

View File

@@ -0,0 +1,80 @@
package filestore
import (
"encoding/hex"
"strconv"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
type storeData struct {
AspUrl string `json:"asp_url"`
AspPubkey string `json:"asp_pubkey"`
WalletType string `json:"wallet_type"`
ClientType string `json:"client_type"`
Network string `json:"network"`
RoundLifetime string `json:"round_lifetime"`
RoundInterval string `json:"round_interval"`
UnilateralExitDelay string `json:"unilateral_exit_delay"`
Dust string `json:"dust"`
BoardingDescriptorTemplate string `json:"boarding_descriptor_template"`
ExplorerURL string `json:"explorer_url"`
ForfeitAddress string `json:"forfeit_address"`
WithTransactionFeed string `json:"with_transaction_feed"`
}
func (d storeData) isEmpty() bool {
if d.AspUrl == "" &&
d.AspPubkey == "" {
return true
}
return false
}
func (d storeData) decode() types.Config {
network := utils.NetworkFromString(d.Network)
roundLifetime, _ := strconv.Atoi(d.RoundLifetime)
roundInterval, _ := strconv.Atoi(d.RoundInterval)
unilateralExitDelay, _ := strconv.Atoi(d.UnilateralExitDelay)
withTransactionFeed, _ := strconv.ParseBool(d.WithTransactionFeed)
dust, _ := strconv.Atoi(d.Dust)
buf, _ := hex.DecodeString(d.AspPubkey)
aspPubkey, _ := secp256k1.ParsePubKey(buf)
explorerURL := d.ExplorerURL
return types.Config{
AspUrl: d.AspUrl,
AspPubkey: aspPubkey,
WalletType: d.WalletType,
ClientType: d.ClientType,
Network: network,
RoundLifetime: int64(roundLifetime),
UnilateralExitDelay: int64(unilateralExitDelay),
RoundInterval: int64(roundInterval),
Dust: uint64(dust),
BoardingDescriptorTemplate: d.BoardingDescriptorTemplate,
ExplorerURL: explorerURL,
ForfeitAddress: d.ForfeitAddress,
WithTransactionFeed: withTransactionFeed,
}
}
func (d storeData) asMap() map[string]string {
return map[string]string{
"asp_url": d.AspUrl,
"asp_pubkey": d.AspPubkey,
"wallet_type": d.WalletType,
"client_type": d.ClientType,
"network": d.Network,
"round_lifetime": d.RoundLifetime,
"round_interval": d.RoundInterval,
"unilateral_exit_delay": d.UnilateralExitDelay,
"dust": d.Dust,
"boarding_descriptor_template": d.BoardingDescriptorTemplate,
"explorer_url": d.ExplorerURL,
"forfeit_address": d.ForfeitAddress,
"with_transaction_feed": d.WithTransactionFeed,
}
}

View File

@@ -0,0 +1,44 @@
package filestore
import (
"os"
"os/user"
"path/filepath"
"strings"
)
func cleanAndExpandPath(path string) string {
// Expand initial ~ to OS specific home directory.
if strings.HasPrefix(path, "~") {
var homeDir string
u, err := user.Current()
if err == nil {
homeDir = u.HomeDir
} else {
homeDir = os.Getenv("HOME")
}
path = strings.Replace(path, "~", homeDir, 1)
}
// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
// but the variables can still be expanded via POSIX-style $VARIABLE.
return filepath.Clean(os.ExpandEnv(path))
}
func makeDirectoryIfNotExists(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
return os.MkdirAll(path, os.ModeDir|0755)
}
return nil
}
func merge(maps ...map[string]string) map[string]string {
merge := make(map[string]string, 0)
for _, m := range maps {
for k, v := range m {
merge[k] = v
}
}
return merge
}

View File

@@ -0,0 +1,57 @@
package inmemorystore
import (
"context"
"sync"
"github.com/ark-network/ark/pkg/client-sdk/types"
)
type store struct {
data *types.Config
lock *sync.RWMutex
}
func NewConfigStore() (types.ConfigStore, error) {
lock := &sync.RWMutex{}
return &store{lock: lock}, nil
}
func (s *store) Close() {}
func (s *store) GetType() string {
return "inmemory"
}
func (s *store) GetDatadir() string {
return ""
}
func (s *store) AddData(
_ context.Context, data types.Config,
) error {
s.lock.Lock()
defer s.lock.Unlock()
s.data = &data
return nil
}
func (s *store) GetData(_ context.Context) (*types.Config, error) {
s.lock.RLock()
defer s.lock.RUnlock()
if s.data == nil {
return nil, nil
}
return s.data, nil
}
func (s *store) CleanData(_ context.Context) error {
s.lock.Lock()
defer s.lock.Unlock()
s.data = nil
return nil
}

View File

@@ -1,55 +0,0 @@
package inmemorystore
import (
"context"
"sync"
"github.com/ark-network/ark/pkg/client-sdk/store"
)
type Store struct {
data *store.StoreData
lock *sync.RWMutex
}
func NewConfigStore() (store.ConfigStore, error) {
lock := &sync.RWMutex{}
return &Store{lock: lock}, nil
}
func (s *Store) GetType() string {
return store.InMemoryStore
}
func (s *Store) GetDatadir() string {
return ""
}
func (s *Store) AddData(
_ context.Context, data store.StoreData,
) error {
s.lock.Lock()
defer s.lock.Unlock()
s.data = &data
return nil
}
func (s *Store) GetData(_ context.Context) (*store.StoreData, error) {
s.lock.RLock()
defer s.lock.RUnlock()
if s.data == nil {
return nil, nil
}
return s.data, nil
}
func (s *Store) CleanData(_ context.Context) error {
s.lock.Lock()
defer s.lock.Unlock()
s.data = nil
return nil
}

View File

@@ -0,0 +1,133 @@
package kvstore
import (
"context"
"fmt"
"path/filepath"
"sort"
"sync"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/dgraph-io/badger/v4"
log "github.com/sirupsen/logrus"
"github.com/timshannon/badgerhold/v4"
)
const (
transactionStoreDir = "transactions"
)
type txStore struct {
db *badgerhold.Store
lock *sync.Mutex
eventCh chan types.TransactionEvent
}
func NewTransactionStore(
dir string, logger badger.Logger,
) (types.TransactionStore, error) {
badgerDb, err := createDB(filepath.Join(dir, transactionStoreDir), logger)
if err != nil {
return nil, fmt.Errorf("failed to open round events store: %s", err)
}
return &txStore{
db: badgerDb,
lock: &sync.Mutex{},
eventCh: make(chan types.TransactionEvent),
}, nil
}
func (s *txStore) AddTransactions(
_ context.Context, txs []types.Transaction,
) error {
for _, tx := range txs {
if err := s.db.Insert(tx.TransactionKey.String(), &tx); err != nil {
return err
}
go func(tx types.Transaction) {
var eventType types.EventType
if tx.IsOOR() {
switch tx.Type {
case types.TxSent:
eventType = types.OORSent
case types.TxReceived:
eventType = types.OORReceived
}
}
if tx.IsBoarding() {
eventType = types.BoardingPending
}
s.sendEvent(types.TransactionEvent{
Tx: tx,
Event: eventType,
})
}(tx)
}
return nil
}
func (s *txStore) UpdateTransactions(
_ context.Context, txs []types.Transaction,
) error {
for _, tx := range txs {
if err := s.db.Upsert(tx.TransactionKey.String(), &tx); err != nil {
return err
}
go func(tx types.Transaction) {
var event types.EventType
if tx.IsOOR() {
event = types.OORSettled
}
if tx.IsBoarding() {
event = types.BoardingSettled
}
s.sendEvent(types.TransactionEvent{
Tx: tx,
Event: event,
})
}(tx)
}
return nil
}
func (s *txStore) GetAllTransactions(
_ context.Context,
) ([]types.Transaction, error) {
var txs []types.Transaction
err := s.db.Find(&txs, nil)
sort.Slice(txs, func(i, j int) bool {
txi := txs[i]
txj := txs[j]
if txi.CreatedAt.Equal(txj.CreatedAt) {
return txi.Type > txj.Type
}
return txi.CreatedAt.After(txj.CreatedAt)
})
return txs, err
}
func (s *txStore) GetEventChannel() chan types.TransactionEvent {
return s.eventCh
}
func (s *txStore) Close() {
if err := s.db.Close(); err != nil {
log.Debugf("error on closing transactions db: %s", err)
}
close(s.eventCh)
}
func (s *txStore) sendEvent(event types.TransactionEvent) {
s.lock.Lock()
defer s.lock.Unlock()
s.eventCh <- event
}

View File

@@ -0,0 +1,47 @@
package kvstore
import (
"time"
"github.com/dgraph-io/badger/v4"
"github.com/dgraph-io/badger/v4/options"
"github.com/timshannon/badgerhold/v4"
)
func createDB(dbDir string, logger badger.Logger) (*badgerhold.Store, error) {
isInMemory := len(dbDir) <= 0
opts := badger.DefaultOptions(dbDir)
opts.Logger = logger
if isInMemory {
opts.InMemory = true
} else {
opts.Compression = options.ZSTD
}
db, err := badgerhold.Open(badgerhold.Options{
Encoder: badgerhold.DefaultEncode,
Decoder: badgerhold.DefaultDecode,
SequenceBandwith: 100,
Options: opts,
})
if err != nil {
return nil, err
}
if !isInMemory {
ticker := time.NewTicker(30 * time.Minute)
go func() {
for {
<-ticker.C
if err := db.Badger().RunValueLogGC(0.5); err != nil && err != badger.ErrNoRewrite {
logger.Errorf("%s", err)
}
}
}()
}
return db, nil
}

View File

@@ -0,0 +1,92 @@
package kvstore
import (
"context"
"errors"
"fmt"
"path/filepath"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/dgraph-io/badger/v4"
log "github.com/sirupsen/logrus"
"github.com/timshannon/badgerhold/v4"
)
const (
vtxoStoreDir = "vtxos"
)
type vtxoStore struct {
db *badgerhold.Store
}
func NewVtxoStore(dir string, logger badger.Logger) (types.VtxoStore, error) {
badgerDb, err := createDB(filepath.Join(dir, vtxoStoreDir), logger)
if err != nil {
return nil, fmt.Errorf("failed to open round events store: %s", err)
}
return &vtxoStore{badgerDb}, nil
}
func (s *vtxoStore) AddVtxos(_ context.Context, vtxos []types.Vtxo) error {
for _, vtxo := range vtxos {
if err := s.db.Insert(vtxo.VtxoKey.String(), &vtxo); err != nil {
return err
}
}
return nil
}
func (s *vtxoStore) UpdateVtxos(_ context.Context, vtxos []types.Vtxo) error {
for _, vtxo := range vtxos {
if err := s.db.Update(vtxo.VtxoKey.String(), &vtxo); err != nil {
return err
}
}
return nil
}
func (s *vtxoStore) GetAllVtxos(
_ context.Context,
) (spendable, spent []types.Vtxo, err error) {
var allVtxos []types.Vtxo
err = s.db.Find(&allVtxos, nil)
if err != nil {
return nil, nil, err
}
for _, vtxo := range allVtxos {
if vtxo.Spent {
spent = append(spent, vtxo)
} else {
spendable = append(spendable, vtxo)
}
}
return
}
func (s *vtxoStore) GetVtxos(
_ context.Context, keys []types.VtxoKey,
) ([]types.Vtxo, error) {
var vtxos []types.Vtxo
for _, key := range keys {
var vtxo types.Vtxo
err := s.db.Get(key.String(), &vtxo)
if err != nil {
if errors.Is(err, badgerhold.ErrNotFound) {
continue
}
return nil, err
}
vtxos = append(vtxos, vtxo)
}
return vtxos, nil
}
func (s *vtxoStore) Close() {
if err := s.db.Close(); err != nil {
log.Debugf("error on closing db: %s", err)
}
}

View File

@@ -0,0 +1,82 @@
package store
import (
"fmt"
filestore "github.com/ark-network/ark/pkg/client-sdk/store/file"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
kvstore "github.com/ark-network/ark/pkg/client-sdk/store/kv"
"github.com/ark-network/ark/pkg/client-sdk/types"
)
type service struct {
configStore types.ConfigStore
vtxoStore types.VtxoStore
txStore types.TransactionStore
}
type Config struct {
ConfigStoreType string
AppDataStoreType string
BaseDir string
}
func NewStore(storeConfig Config) (types.Store, error) {
var (
configStore types.ConfigStore
vtxoStore types.VtxoStore
txStore types.TransactionStore
err error
dir = storeConfig.BaseDir
)
switch storeConfig.ConfigStoreType {
case types.InMemoryStore:
configStore, err = inmemorystore.NewConfigStore()
case types.FileStore:
configStore, err = filestore.NewConfigStore(dir)
default:
err = fmt.Errorf("unknown config store type")
}
if err != nil {
return nil, err
}
if len(storeConfig.AppDataStoreType) > 0 {
switch storeConfig.AppDataStoreType {
case types.KVStore:
vtxoStore, err = kvstore.NewVtxoStore(dir, nil)
if err != nil {
return nil, err
}
txStore, err = kvstore.NewTransactionStore(dir, nil)
default:
err = fmt.Errorf("unknown appdata store type")
}
if err != nil {
return nil, err
}
}
return &service{configStore, vtxoStore, txStore}, nil
}
func (s *service) ConfigStore() types.ConfigStore {
return s.configStore
}
func (s *service) VtxoStore() types.VtxoStore {
return s.vtxoStore
}
func (s *service) TransactionStore() types.TransactionStore {
return s.txStore
}
func (s *service) Close() {
s.configStore.Close()
s.vtxoStore.Close()
s.txStore.Close()
}

View File

@@ -3,21 +3,24 @@ package store_test
import (
"context"
"testing"
"time"
"github.com/ark-network/ark/common"
"github.com/ark-network/ark/pkg/client-sdk/client"
"github.com/ark-network/ark/pkg/client-sdk/store"
filestore "github.com/ark-network/ark/pkg/client-sdk/store/file"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
filedb "github.com/ark-network/ark/pkg/client-sdk/store/file"
inmemorydb "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
sdktypes "github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
"github.com/btcsuite/btcd/btcec/v2"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
)
func TestStore(t *testing.T) {
key, _ := btcec.NewPrivateKey()
ctx := context.Background()
testStoreData := store.StoreData{
testStoreData := sdktypes.Config{
AspUrl: "localhost:7070",
AspPubkey: key.PubKey(),
WalletType: wallet.SingleKeyWallet,
@@ -35,10 +38,10 @@ func TestStore(t *testing.T) {
name string
}{
{
name: store.InMemoryStore,
name: sdktypes.InMemoryStore,
},
{
name: store.FileStore,
name: sdktypes.FileStore,
},
}
@@ -47,13 +50,13 @@ func TestStore(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var storeSvc store.ConfigStore
var storeSvc sdktypes.ConfigStore
var err error
switch tt.name {
case store.InMemoryStore:
storeSvc, err = inmemorystore.NewConfigStore()
case store.FileStore:
storeSvc, err = filestore.NewConfigStore(t.TempDir())
case sdktypes.InMemoryStore:
storeSvc, err = inmemorydb.NewConfigStore()
case sdktypes.FileStore:
storeSvc, err = filedb.NewConfigStore(t.TempDir())
}
require.NoError(t, err)
require.NotNil(t, storeSvc)
@@ -91,3 +94,55 @@ func TestStore(t *testing.T) {
})
}
}
func TestNewService(t *testing.T) {
ctx := context.Background()
testDir := t.TempDir()
dbConfig := store.Config{
ConfigStoreType: sdktypes.FileStore,
AppDataStoreType: sdktypes.KVStore,
BaseDir: testDir,
}
service, err := store.NewStore(dbConfig)
require.NoError(t, err)
require.NotNil(t, service)
go func() {
eventCh := service.TransactionStore().GetEventChannel()
for tx := range eventCh {
log.Infof("Tx inserted: %d %v", tx.Tx.Amount, tx.Tx.Type)
}
}()
txStore := service.TransactionStore()
require.NotNil(t, txStore)
testTxs := []sdktypes.Transaction{
{
TransactionKey: sdktypes.TransactionKey{
RoundTxid: "tx1",
},
Amount: 1000,
Type: sdktypes.TxSent,
CreatedAt: time.Now(),
},
{
TransactionKey: sdktypes.TransactionKey{
RoundTxid: "tx2",
},
Amount: 2000,
Type: sdktypes.TxReceived,
CreatedAt: time.Now(),
},
}
err = txStore.AddTransactions(ctx, testTxs)
require.NoError(t, err)
retrievedTxs, err := txStore.GetAllTransactions(ctx)
require.NoError(t, err)
require.Len(t, retrievedTxs, 2)
service.Close()
}

View File

@@ -1,36 +0,0 @@
package store
import (
"context"
"github.com/ark-network/ark/common"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
const (
InMemoryStore = "inmemory"
FileStore = "file"
)
type StoreData struct {
AspUrl string
AspPubkey *secp256k1.PublicKey
WalletType string
ClientType string
Network common.Network
RoundLifetime int64
RoundInterval int64
UnilateralExitDelay int64
Dust uint64
BoardingDescriptorTemplate string
ExplorerURL string
ForfeitAddress string
}
type ConfigStore interface {
GetType() string
GetDatadir() string
AddData(ctx context.Context, data StoreData) error
GetData(ctx context.Context) (*StoreData, error)
CleanData(ctx context.Context) error
}

View File

@@ -2,7 +2,6 @@ package arksdk
import (
"fmt"
"time"
grpcclient "github.com/ark-network/ark/pkg/client-sdk/client/grpc"
restclient "github.com/ark-network/ark/pkg/client-sdk/client/rest"
@@ -21,12 +20,13 @@ var (
)
type InitArgs struct {
ClientType string
WalletType string
AspUrl string
Seed string
Password string
ExplorerURL string
ClientType string
WalletType string
AspUrl string
Seed string
Password string
ExplorerURL string
ListenTransactionStream bool
}
func (a InitArgs) validate() error {
@@ -60,12 +60,13 @@ func (a InitArgs) validate() error {
}
type InitWithWalletArgs struct {
ClientType string
Wallet wallet.WalletService
AspUrl string
Seed string
Password string
ExplorerURL string
ClientType string
Wallet wallet.WalletService
AspUrl string
Seed string
Password string
ExplorerURL string
ListenTransactionStream bool
}
func (a InitWithWalletArgs) validate() error {
@@ -122,20 +123,3 @@ type balanceRes struct {
offchainBalanceByExpiration map[int64]uint64
err error
}
const (
TxSent TxType = "sent"
TxReceived TxType = "received"
)
type TxType string
type Transaction struct {
BoardingTxid string
RoundTxid string
RedeemTxid string
Amount uint64
Type TxType
IsPending bool
CreatedAt time.Time
}

View File

@@ -0,0 +1,35 @@
package types
import "context"
type Store interface {
ConfigStore() ConfigStore
TransactionStore() TransactionStore
VtxoStore() VtxoStore
Close()
}
type ConfigStore interface {
GetType() string
GetDatadir() string
AddData(ctx context.Context, data Config) error
GetData(ctx context.Context) (*Config, error)
CleanData(ctx context.Context) error
Close()
}
type TransactionStore interface {
AddTransactions(ctx context.Context, txs []Transaction) error
UpdateTransactions(ctx context.Context, txs []Transaction) error
GetAllTransactions(ctx context.Context) ([]Transaction, error)
GetEventChannel() chan TransactionEvent
Close()
}
type VtxoStore interface {
AddVtxos(ctx context.Context, vtxos []Vtxo) error
UpdateVtxos(ctx context.Context, vtxos []Vtxo) error
GetAllVtxos(ctx context.Context) (spendable []Vtxo, spent []Vtxo, err error)
GetVtxos(ctx context.Context, keys []VtxoKey) ([]Vtxo, error)
Close()
}

View File

@@ -0,0 +1,105 @@
package types
import (
"fmt"
"strconv"
"time"
"github.com/ark-network/ark/common"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
const (
InMemoryStore = "inmemory"
FileStore = "file"
KVStore = "kv"
)
type Config struct {
AspUrl string
AspPubkey *secp256k1.PublicKey
WalletType string
ClientType string
Network common.Network
RoundLifetime int64
RoundInterval int64
UnilateralExitDelay int64
Dust uint64
BoardingDescriptorTemplate string
ExplorerURL string
ForfeitAddress string
WithTransactionFeed bool
}
type VtxoKey struct {
Txid string
VOut uint32
}
func (v VtxoKey) String() string {
return fmt.Sprintf("%s:%s", v.Txid, strconv.Itoa(int(v.VOut)))
}
type Vtxo struct {
VtxoKey
Amount uint64
RoundTxid string
ExpiresAt *time.Time
RedeemTx string
UnconditionalForfeitTxs []string
Pending bool
SpentBy string
Spent bool
}
const (
TxSent TxType = "SENT"
TxReceived TxType = "RECEIVED"
)
type TxType string
type TransactionKey struct {
BoardingTxid string
RoundTxid string
RedeemTxid string
}
func (t TransactionKey) String() string {
return fmt.Sprintf("%s%s%s", t.BoardingTxid, t.RoundTxid, t.RedeemTxid)
}
type Transaction struct {
TransactionKey
Amount uint64
Type TxType
IsPending bool
CreatedAt time.Time
}
func (t Transaction) IsRound() bool {
return t.RoundTxid != ""
}
func (t Transaction) IsBoarding() bool {
return t.BoardingTxid != ""
}
func (t Transaction) IsOOR() bool {
return t.RedeemTxid != ""
}
const (
BoardingPending EventType = "BOARDING_PENDING"
BoardingSettled EventType = "BOARDING_SETTLED"
OORSent EventType = "OOR_SENT"
OORReceived EventType = "OOR_RECEIVED"
OORSettled EventType = "OOR_SETTLED"
)
type EventType string
type TransactionEvent struct {
Tx Transaction
Event EventType
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/ark-network/ark/common/bitcointree"
"github.com/ark-network/ark/pkg/client-sdk/explorer"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
walletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
@@ -26,14 +26,18 @@ type bitcoinWallet struct {
}
func NewBitcoinWallet(
configStore store.ConfigStore, walletStore walletstore.WalletStore,
configStore types.ConfigStore, walletStore walletstore.WalletStore,
) (wallet.WalletService, error) {
walletData, err := walletStore.GetWallet()
if err != nil {
return nil, err
}
return &bitcoinWallet{
&singlekeyWallet{configStore, walletStore, nil, walletData},
&singlekeyWallet{
configStore: configStore,
walletStore: walletStore,
walletData: walletData,
},
}, nil
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/ark-network/ark/common/tree"
"github.com/ark-network/ark/pkg/client-sdk/explorer"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
walletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
@@ -27,14 +27,18 @@ type liquidWallet struct {
}
func NewLiquidWallet(
configStore store.ConfigStore, walletStore walletstore.WalletStore,
configStore types.ConfigStore, walletStore walletstore.WalletStore,
) (wallet.WalletService, error) {
walletData, err := walletStore.GetWallet()
if err != nil {
return nil, err
}
return &liquidWallet{
&singlekeyWallet{configStore, walletStore, nil, walletData},
&singlekeyWallet{
configStore: configStore,
walletStore: walletStore,
walletData: walletData,
},
}, nil
}

View File

@@ -3,7 +3,7 @@ package store_test
import (
"testing"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
walletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store"
filestore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store/file"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store/inmemory"
@@ -24,10 +24,10 @@ func TestWalletStore(t *testing.T) {
args []interface{}
}{
{
name: store.InMemoryStore,
name: types.InMemoryStore,
},
{
name: store.FileStore,
name: types.FileStore,
},
}
@@ -38,7 +38,7 @@ func TestWalletStore(t *testing.T) {
var storeSvc walletstore.WalletStore
var err error
if tt.name == store.InMemoryStore {
if tt.name == types.InMemoryStore {
storeSvc, err = inmemorystore.NewWalletStore()
} else {
storeSvc, err = filestore.NewWalletStore(t.TempDir())

View File

@@ -7,14 +7,14 @@ import (
"fmt"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
walletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
type singlekeyWallet struct {
configStore store.ConfigStore
configStore types.ConfigStore
walletStore walletstore.WalletStore
privateKey *secp256k1.PrivateKey
walletData *walletstore.WalletData

View File

@@ -7,8 +7,8 @@ import (
"github.com/ark-network/ark/common"
"github.com/ark-network/ark/pkg/client-sdk/client"
"github.com/ark-network/ark/pkg/client-sdk/store"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
sdktypes "github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
singlekeywallet "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey"
inmemorywalletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store/inmemory"
@@ -20,7 +20,7 @@ func TestWallet(t *testing.T) {
ctx := context.Background()
key, _ := btcec.NewPrivateKey()
password := "password"
testStoreData := store.StoreData{
testStoreData := sdktypes.Config{
AspUrl: "localhost:7070",
AspPubkey: key.PubKey(),
WalletType: wallet.SingleKeyWallet,

View File

@@ -12,7 +12,7 @@ import (
"syscall/js"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
@@ -33,26 +33,26 @@ type storeData struct {
Dust string `json:"dust"`
ForfeitAddress string `json:"forfeit_address"`
BoardingDescriptorTemplate string `json:"boarding_descriptor_template"`
WithTransactionFeed string `json:"with_transaction_feed"`
}
type localStorageStore struct {
type configStore struct {
store js.Value
}
func NewLocalStorageStore() (store.ConfigStore, error) {
store := js.Global().Get("localStorage")
return &localStorageStore{store}, nil
func NewConfigStore(store js.Value) types.ConfigStore {
return &configStore{store}
}
func (s *localStorageStore) GetType() string {
func (s *configStore) GetType() string {
return LocalStorageStore
}
func (s *localStorageStore) GetDatadir() string {
func (s *configStore) GetDatadir() string {
return ""
}
func (s *localStorageStore) AddData(ctx context.Context, data store.StoreData) error {
func (s *configStore) AddData(ctx context.Context, data types.Config) error {
sd := &storeData{
AspUrl: data.AspUrl,
AspPubkey: hex.EncodeToString(data.AspPubkey.SerializeCompressed()),
@@ -70,7 +70,7 @@ func (s *localStorageStore) AddData(ctx context.Context, data store.StoreData) e
return s.writeData(sd)
}
func (s *localStorageStore) GetData(ctx context.Context) (*store.StoreData, error) {
func (s *configStore) GetData(ctx context.Context) (*types.Config, error) {
key := s.store.Call("getItem", "asp_pubkey")
if key.IsNull() || key.IsUndefined() {
return nil, nil
@@ -92,8 +92,9 @@ func (s *localStorageStore) GetData(ctx context.Context) (*store.StoreData, erro
roundInterval, _ := strconv.Atoi(s.store.Call("getItem", "round_interval").String())
unilateralExitDelay, _ := strconv.Atoi(s.store.Call("getItem", "unilateral_exit_delay").String())
dust, _ := strconv.Atoi(s.store.Call("getItem", "min_relay_fee").String())
withTxFeed, _ := strconv.ParseBool(s.store.Call("getItem", "with_transaction_feed").String())
return &store.StoreData{
return &types.Config{
AspUrl: s.store.Call("getItem", "asp_url").String(),
AspPubkey: aspPubkey,
WalletType: s.store.Call("getItem", "wallet_type").String(),
@@ -106,17 +107,20 @@ func (s *localStorageStore) GetData(ctx context.Context) (*store.StoreData, erro
ExplorerURL: s.store.Call("getItem", "explorer_url").String(),
ForfeitAddress: s.store.Call("getItem", "forfeit_address").String(),
BoardingDescriptorTemplate: s.store.Call("getItem", "boarding_descriptor_template").String(),
WithTransactionFeed: withTxFeed,
}, nil
}
func (s *localStorageStore) CleanData(ctx context.Context) error {
func (s *configStore) CleanData(ctx context.Context) error {
if err := s.writeData(&storeData{}); err != nil {
return fmt.Errorf("failed to write to store: %s", err)
}
return nil
}
func (s *localStorageStore) writeData(data *storeData) error {
func (s *configStore) Close() {}
func (s *configStore) writeData(data *storeData) error {
dataMap := make(map[string]string)
buf, err := json.Marshal(data)
if err != nil {

View File

@@ -10,7 +10,7 @@ import (
"syscall/js"
arksdk "github.com/ark-network/ark/pkg/client-sdk"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
singlekeywallet "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey"
walletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store"
@@ -18,7 +18,7 @@ import (
var (
arkSdkClient arksdk.ArkClient
configStore store.ConfigStore
store types.Store
)
func init() {
@@ -49,11 +49,11 @@ func init() {
}
func NewCovenantClient(
ctx context.Context, storeSvc store.ConfigStore,
ctx context.Context, storeSvc types.Store,
) error {
var err error
data, err := storeSvc.GetData(ctx)
data, err := storeSvc.ConfigStore().GetData(ctx)
if err != nil {
return err
}
@@ -64,7 +64,7 @@ func NewCovenantClient(
var walletSvc wallet.WalletService
switch data.WalletType {
case arksdk.SingleKeyWallet:
walletSvc, err = getSingleKeyWallet(storeSvc, data.Network.Name)
walletSvc, err = getSingleKeyWallet(storeSvc.ConfigStore(), data.Network.Name)
if err != nil {
return err
}
@@ -78,17 +78,17 @@ func NewCovenantClient(
js.Global().Get("console").Call("error", err.Error())
return err
}
configStore = storeSvc
store = storeSvc
select {}
}
func NewCovenantlessClient(
ctx context.Context, storeSvc store.ConfigStore,
ctx context.Context, storeSvc types.Store,
) error {
var err error
data, err := storeSvc.GetData(ctx)
data, err := storeSvc.ConfigStore().GetData(ctx)
if err != nil {
return err
}
@@ -99,7 +99,7 @@ func NewCovenantlessClient(
var walletSvc wallet.WalletService
switch data.WalletType {
case arksdk.SingleKeyWallet:
walletSvc, err = getSingleKeyWallet(storeSvc, data.Network.Name)
walletSvc, err = getSingleKeyWallet(storeSvc.ConfigStore(), data.Network.Name)
if err != nil {
return err
}
@@ -113,7 +113,7 @@ func NewCovenantlessClient(
js.Global().Get("console").Call("error", err.Error())
return err
}
configStore = storeSvc
store = storeSvc
select {}
}
@@ -127,7 +127,7 @@ func getWalletStore(storeType string) (walletstore.WalletStore, error) {
}
func getSingleKeyWallet(
configStore store.ConfigStore, network string,
configStore types.ConfigStore, network string,
) (wallet.WalletService, error) {
walletStore, err := getWalletStore(configStore.GetType())
if err != nil {

View File

@@ -0,0 +1,34 @@
//go:build js && wasm
// +build js,wasm
package browser
import (
"syscall/js"
"github.com/ark-network/ark/pkg/client-sdk/types"
)
// TODO: support vtxo and transaction stores localstorage impls.
type localStorageStore struct {
configStore types.ConfigStore
}
func NewLocalStorageStore() types.Store {
configStore := NewConfigStore(js.Global().Get("localStorage"))
return &localStorageStore{configStore}
}
func (s *localStorageStore) ConfigStore() types.ConfigStore {
return s.configStore
}
func (s *localStorageStore) VtxoStore() types.VtxoStore {
return nil
}
func (s *localStorageStore) TransactionStore() types.TransactionStore {
return nil
}
func (s *localStorageStore) Close() {}

View File

@@ -35,7 +35,9 @@ func LogWrapper() js.Func {
func InitWrapper() js.Func {
return JSPromise(func(args []js.Value) (interface{}, error) {
if len(args) != 6 {
// TODO: add another withTransactionFeed args to configure client listen to
// new txs from the server. Requires server to use websockets.
if len(args) != 7 {
return nil, errors.New("invalid number of args")
}
chain := args[5].String()
@@ -43,6 +45,7 @@ func InitWrapper() js.Func {
return nil, errors.New("invalid chain, select either 'bitcoin' or 'liquid'")
}
configStore := store.ConfigStore()
var walletSvc wallet.WalletService
switch args[0].String() {
case arksdk.SingleKeyWallet:
@@ -66,11 +69,12 @@ func InitWrapper() js.Func {
}
err := arkSdkClient.InitWithWallet(context.Background(), arksdk.InitWithWalletArgs{
ClientType: args[1].String(),
Wallet: walletSvc,
AspUrl: args[2].String(),
Seed: args[3].String(),
Password: args[4].String(),
ClientType: args[1].String(),
Wallet: walletSvc,
AspUrl: args[2].String(),
Seed: args[3].String(),
Password: args[4].String(),
ExplorerURL: args[6].String(),
})
// Add this log message

View File

@@ -5,36 +5,19 @@ package main
import (
"context"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
"github.com/ark-network/ark/pkg/client-sdk/wasm/browser"
)
func main() {
c := make(chan struct{}, 0)
var (
ctx = context.Background()
)
store, err := browser.NewLocalStorageStore()
if err != nil {
ctx := context.Background()
storeSvc := browser.NewLocalStorageStore()
if err := browser.NewCovenantlessClient(ctx, storeSvc); err != nil {
browser.ConsoleError(err)
return
}
if store != nil {
if err := browser.NewCovenantlessClient(ctx, store); err != nil {
browser.ConsoleError(err)
return
}
} else {
storeSvc, err := inmemorystore.NewConfigStore()
if err != nil {
browser.ConsoleError(err)
return
}
if err := browser.NewCovenantlessClient(ctx, storeSvc); err != nil {
browser.ConsoleError(err)
return
}
}
println("ARK SDK WebAssembly module initialized")
<-c
}

View File

@@ -1050,7 +1050,8 @@ func (s *covenantlessService) finalizeRound() {
log.Debugf("signing round transaction %s\n", round.Id)
boardingInputs := make([]int, 0)
boardingInputsIndexes := make([]int, 0)
boardingInputs := make([]domain.VtxoKey, 0)
roundTx, err := psbt.NewFromRawBytes(strings.NewReader(round.UnsignedTx), true)
if err != nil {
changes = round.Fail(fmt.Errorf("failed to parse round tx: %s", err))
@@ -1067,14 +1068,18 @@ func (s *covenantlessService) finalizeRound() {
return
}
boardingInputs = append(boardingInputs, i)
boardingInputsIndexes = append(boardingInputsIndexes, i)
boardingInputs = append(boardingInputs, domain.VtxoKey{
Txid: roundTx.UnsignedTx.TxIn[i].PreviousOutPoint.Hash.String(),
VOut: roundTx.UnsignedTx.TxIn[i].PreviousOutPoint.Index,
})
}
}
signedRoundTx := round.UnsignedTx
if len(boardingInputs) > 0 {
signedRoundTx, err = s.wallet.SignTransactionTapscript(ctx, signedRoundTx, boardingInputs)
if len(boardingInputsIndexes) > 0 {
signedRoundTx, err = s.wallet.SignTransactionTapscript(ctx, signedRoundTx, boardingInputsIndexes)
if err != nil {
changes = round.Fail(fmt.Errorf("failed to sign round tx: %s", err))
log.WithError(err).Warn("failed to sign round tx")
@@ -1102,6 +1107,15 @@ func (s *covenantlessService) finalizeRound() {
return
}
go func() {
s.transactionEventsCh <- RoundTransactionEvent{
RoundTxID: round.Txid,
SpentVtxos: getSpentVtxos(round.Payments),
SpendableVtxos: s.getNewVtxos(round),
ClaimedBoardingInputs: boardingInputs,
}
}()
log.Debugf("finalized round %s with pool tx %s", round.Id, round.Txid)
}
@@ -1270,25 +1284,6 @@ func (s *covenantlessService) updateVtxoSet(round *domain.Round) {
}()
}
go func() {
// nolint:all
tx, _ := psbt.NewFromRawBytes(strings.NewReader(round.UnsignedTx), true)
boardingInputs := make([]domain.VtxoKey, 0)
for i, in := range tx.Inputs {
if len(in.TaprootLeafScript) > 0 {
boardingInputs = append(boardingInputs, domain.VtxoKey{
Txid: tx.UnsignedTx.TxIn[i].PreviousOutPoint.Hash.String(),
VOut: tx.UnsignedTx.TxIn[i].PreviousOutPoint.Index,
})
}
}
s.transactionEventsCh <- RoundTransactionEvent{
RoundTxID: round.Txid,
SpentVtxos: getSpentVtxos(round.Payments),
SpendableVtxos: s.getNewVtxos(round),
ClaimedBoardingInputs: boardingInputs,
}
}()
}
func (s *covenantlessService) propagateEvents(round *domain.Round) {

View File

@@ -16,7 +16,8 @@ import (
grpcclient "github.com/ark-network/ark/pkg/client-sdk/client/grpc"
"github.com/ark-network/ark/pkg/client-sdk/explorer"
"github.com/ark-network/ark/pkg/client-sdk/redemption"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
utils "github.com/ark-network/ark/server/test/e2e"
"github.com/stretchr/testify/require"
)
@@ -320,10 +321,14 @@ func setupAspWallet() error {
}
func setupArkSDK(t *testing.T) (arksdk.ArkClient, client.ASPClient) {
storeSvc, err := inmemorystore.NewConfigStore()
appDataStore, err := store.NewStore(store.Config{
ConfigStoreType: types.FileStore,
AppDataStoreType: types.KVStore,
BaseDir: t.TempDir(),
})
require.NoError(t, err)
client, err := arksdk.NewCovenantClient(storeSvc)
client, err := arksdk.NewCovenantClient(appDataStore)
require.NoError(t, err)
err = client.Init(context.Background(), arksdk.InitArgs{

View File

@@ -16,7 +16,8 @@ import (
grpcclient "github.com/ark-network/ark/pkg/client-sdk/client/grpc"
"github.com/ark-network/ark/pkg/client-sdk/explorer"
"github.com/ark-network/ark/pkg/client-sdk/redemption"
inmemorystore "github.com/ark-network/ark/pkg/client-sdk/store/inmemory"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/types"
utils "github.com/ark-network/ark/server/test/e2e"
"github.com/stretchr/testify/require"
)
@@ -505,10 +506,14 @@ func setupAspWallet() error {
}
func setupArkSDK(t *testing.T) (arksdk.ArkClient, client.ASPClient) {
storeSvc, err := inmemorystore.NewConfigStore()
appDataStore, err := store.NewStore(store.Config{
ConfigStoreType: types.FileStore,
AppDataStoreType: types.KVStore,
BaseDir: t.TempDir(),
})
require.NoError(t, err)
client, err := arksdk.NewCovenantlessClient(storeSvc)
client, err := arksdk.NewCovenantlessClient(appDataStore)
require.NoError(t, err)
err = client.Init(context.Background(), arksdk.InitArgs{