diff --git a/asserter/block.go b/asserter/block.go index 1ab0dedf..3d9c61a0 100644 --- a/asserter/block.go +++ b/asserter/block.go @@ -55,7 +55,7 @@ func Amount(amount *types.Amount) error { return ErrAmountValueMissing } - _, ok := new(big.Int).SetString(amount.Value, 10) + _, ok := new(big.Int).SetString(amount.Value, 10) // nolint: gomnd if !ok { return ErrAmountIsNotInt } @@ -336,7 +336,7 @@ func (a *Asserter) Operations( // nolint:gocognit if a.validations.Enabled { if op.Type == a.validations.Payment.Name { - val, _ := new(big.Int).SetString(op.Amount.Value, 10) + val, _ := new(big.Int).SetString(op.Amount.Value, 10) // nolint: gomnd paymentTotal.Add(paymentTotal, val) paymentCount++ } diff --git a/client/api_account.go b/client/api_account.go index d6e49a9a..118febee 100644 --- a/client/api_account.go +++ b/client/api_account.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/api_block.go b/client/api_block.go index d42f7a02..91dee03d 100644 --- a/client/api_block.go +++ b/client/api_block.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/api_call.go b/client/api_call.go index f8ae9968..c6cb09af 100644 --- a/client/api_call.go +++ b/client/api_call.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/api_construction.go b/client/api_construction.go index 05b1c0ff..9472fec7 100644 --- a/client/api_construction.go +++ b/client/api_construction.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/api_events.go b/client/api_events.go index 086b7dbb..2edaf366 100644 --- a/client/api_events.go +++ b/client/api_events.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/api_mempool.go b/client/api_mempool.go index b694c682..e5f10c5a 100644 --- a/client/api_mempool.go +++ b/client/api_mempool.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/api_network.go b/client/api_network.go index a471b4aa..c88114cd 100644 --- a/client/api_network.go +++ b/client/api_network.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/api_search.go b/client/api_search.go index a84d0068..391c28d5 100644 --- a/client/api_search.go +++ b/client/api_search.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/client.go b/client/client.go index b7979723..4a5fd571 100644 --- a/client/client.go +++ b/client/client.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/configuration.go b/client/configuration.go index 0d4d218d..57bfe875 100644 --- a/client/configuration.go +++ b/client/configuration.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/response.go b/client/response.go index 12facd8c..7fbf1a00 100644 --- a/client/response.go +++ b/client/response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/constructor/job/job.go b/constructor/job/job.go index d09fa66f..02bc16b8 100644 --- a/constructor/job/job.go +++ b/constructor/job/job.go @@ -121,7 +121,7 @@ func (j *Job) unmarshalNumber( return nil, ErrVariableNotFound } - i, ok := new(big.Int).SetString(value.String(), 10) + i, ok := new(big.Int).SetString(value.String(), 10) // nolint: gomnd if !ok { return nil, ErrVariableIncorrectFormat } diff --git a/fetcher/account.go b/fetcher/account.go index 1dbbd9e8..3c1cf3fb 100644 --- a/fetcher/account.go +++ b/fetcher/account.go @@ -18,6 +18,8 @@ import ( "context" "fmt" + "github.com/fatih/color" + "github.com/coinbase/rosetta-sdk-go/asserter" "github.com/coinbase/rosetta-sdk-go/types" ) @@ -33,8 +35,10 @@ func (f *Fetcher) AccountBalance( currencies []*types.Currency, ) (*types.BlockIdentifier, []*types.Amount, map[string]interface{}, *Error) { if err := f.connectionSemaphore.Acquire(ctx, semaphoreRequestWeight); err != nil { + err = fmt.Errorf("failed to acquire semaphore: %w%s", err, f.metaData) + color.Red(err.Error()) return nil, nil, nil, &Error{ - Err: fmt.Errorf("failed to acquire semaphore: %w", err), + Err: err, } } defer f.connectionSemaphore.Release(semaphoreRequestWeight) @@ -55,11 +59,10 @@ func (f *Fetcher) AccountBalance( block, response, ); err != nil { + err = fmt.Errorf("/account/balance response is invalid: %w%s", err, f.metaData) + color.Red(err.Error()) fetcherErr := &Error{ - Err: fmt.Errorf( - "/account/balance response is invalid: %w", - err, - ), + Err: err, } return nil, nil, nil, fetcherErr } @@ -101,15 +104,19 @@ func (f *Fetcher) AccountBalanceRetry( } if is, _ := asserter.Err(err.Err); is { + errForPrint := fmt.Errorf("/account/balance not attempting retry: %w", err.Err) + color.Red(errForPrint.Error()) fetcherErr := &Error{ - Err: fmt.Errorf("/account/balance not attempting retry: %w", err.Err), + Err: errForPrint, ClientErr: err.ClientErr, } return nil, nil, nil, fetcherErr } + msg := fmt.Sprintf("/account/balance %s%s", types.PrintStruct(account), f.metaData) + color.Cyan(msg) if err := tryAgain( - fmt.Sprintf("/account/balance %s", types.PrintStruct(account)), + msg, backoffRetries, err, ); err != nil { @@ -128,8 +135,10 @@ func (f *Fetcher) AccountCoins( currencies []*types.Currency, ) (*types.BlockIdentifier, []*types.Coin, map[string]interface{}, *Error) { if err := f.connectionSemaphore.Acquire(ctx, semaphoreRequestWeight); err != nil { + err = fmt.Errorf("failed to acquire semaphore: %w%s", err, f.metaData) + color.Red(err.Error()) return nil, nil, nil, &Error{ - Err: fmt.Errorf("failed to acquire semaphore: %w", err), + Err: err, } } defer f.connectionSemaphore.Release(semaphoreRequestWeight) @@ -149,11 +158,10 @@ func (f *Fetcher) AccountCoins( if err := asserter.AccountCoinsResponse( response, ); err != nil { + err = fmt.Errorf("/account/coins response is invalid: %w%s", err, f.metaData) + color.Red(err.Error()) fetcherErr := &Error{ - Err: fmt.Errorf( - "/account/coins response is invalid: %w", - err, - ), + Err: err, } return nil, nil, nil, fetcherErr } @@ -194,15 +202,23 @@ func (f *Fetcher) AccountCoinsRetry( } if is, _ := asserter.Err(err.Err); is { + errForPrint := fmt.Errorf( + "/account/coins not attempting retry: %w%s", + err.Err, + f.metaData, + ) + color.Red(errForPrint.Error()) fetcherErr := &Error{ - Err: fmt.Errorf("/account/coins not attempting retry: %w", err.Err), + Err: errForPrint, ClientErr: err.ClientErr, } return nil, nil, nil, fetcherErr } + msg := fmt.Sprintf("/account/coins %s%s", types.PrintStruct(account), f.metaData) + color.Cyan(msg) if err := tryAgain( - fmt.Sprintf("/account/coins %s", types.PrintStruct(account)), + msg, backoffRetries, err, ); err != nil { diff --git a/fetcher/block.go b/fetcher/block.go index 13c463ff..53c04e1e 100644 --- a/fetcher/block.go +++ b/fetcher/block.go @@ -18,6 +18,7 @@ import ( "context" "fmt" + "github.com/fatih/color" "golang.org/x/sync/errgroup" "github.com/coinbase/rosetta-sdk-go/asserter" @@ -72,8 +73,10 @@ func (f *Fetcher) fetchChannelTransactions( ) *Error { // We keep the lock for all transactions we fetch in this goroutine. if err := f.connectionSemaphore.Acquire(ctx, semaphoreRequestWeight); err != nil { + err = fmt.Errorf("failed to acquire semaphore: %w%s", err, f.metaData) + color.Red(err.Error()) return &Error{ - Err: fmt.Errorf("failed to acquire semaphore: %w", err), + Err: err, } } defer f.connectionSemaphore.Release(semaphoreRequestWeight) @@ -111,6 +114,7 @@ func (f *Fetcher) fetchChannelTransactions( )) txFetchErr := fmt.Sprintf("transaction %s", types.PrintStruct(transactionIdentifier)) + color.Red("%s%s", txFetchErr, f.metaData) if err := tryAgain(txFetchErr, backoffRetries, fetchErr); err != nil { return err } @@ -214,8 +218,10 @@ func (f *Fetcher) UnsafeBlock( blockIdentifier *types.PartialBlockIdentifier, ) (*types.Block, *Error) { if err := f.connectionSemaphore.Acquire(ctx, semaphoreRequestWeight); err != nil { + err = fmt.Errorf("failed to acquire semaphore: %w%s", err, f.metaData) + color.Red(err.Error()) return nil, &Error{ - Err: fmt.Errorf("failed to acquire semaphore: %w", err), + Err: err, } } defer f.connectionSemaphore.Release(semaphoreRequestWeight) @@ -273,8 +279,10 @@ func (f *Fetcher) Block( } if err := f.Asserter.Block(block); err != nil { + err = fmt.Errorf("/block response is invalid: %w%s", err, f.metaData) + color.Red(err.Error()) fetcherErr := &Error{ - Err: fmt.Errorf("/block response is invalid: %w", err), + Err: err, } return nil, fetcherErr } @@ -313,14 +321,17 @@ func (f *Fetcher) BlockRetry( } if is, _ := asserter.Err(err.Err); is { + errForPrint := fmt.Errorf("/block not attempting retry: %w%s", err.Err, f.metaData) + color.Red(errForPrint.Error()) fetcherErr := &Error{ - Err: fmt.Errorf("/block not attempting retry: %w", err.Err), + Err: errForPrint, ClientErr: err.ClientErr, } return nil, fetcherErr } blockFetchErr := fmt.Sprintf("block %s", types.PrintStruct(blockIdentifier)) + color.Red("%s%s", blockFetchErr, f.metaData) if err := tryAgain(blockFetchErr, backoffRetries, err); err != nil { return nil, err } diff --git a/fetcher/configuration.go b/fetcher/configuration.go index 3df344bf..90b2b2fd 100644 --- a/fetcher/configuration.go +++ b/fetcher/configuration.go @@ -99,3 +99,10 @@ func WithForceRetry() Option { f.forceRetry = true } } + +// add a metaData map to fetcher +func WithMetaData(metaData string) Option { + return func(f *Fetcher) { + f.metaData = metaData + } +} diff --git a/fetcher/errors.go b/fetcher/errors.go index 3c97603b..eb88a4c0 100644 --- a/fetcher/errors.go +++ b/fetcher/errors.go @@ -20,6 +20,8 @@ import ( "fmt" "log" + "github.com/fatih/color" + utils "github.com/coinbase/rosetta-sdk-go/errors" "github.com/coinbase/rosetta-sdk-go/types" ) @@ -50,12 +52,21 @@ func (f *Fetcher) RequestFailedError( // If there is a *types.Error assertion error, we log it instead // of exiting. Exiting abruptly here may cause unintended consequences. if assertionErr := f.Asserter.Error(rosettaErr); assertionErr != nil { - log.Printf("error %s assertion failed: %s", types.PrintStruct(rosettaErr), assertionErr) + msg := fmt.Sprintf( + "error %s assertion failed: %s%s", + types.PrintStruct(rosettaErr), + assertionErr, + f.metaData, + ) + color.Cyan(msg) + log.Println(msg) } } + errForPrint := fmt.Errorf("%s %s: %w%s", message, err.Error(), ErrRequestFailed, f.metaData) + color.Red(errForPrint.Error()) return &Error{ - Err: fmt.Errorf("%s %s: %w", message, err.Error(), ErrRequestFailed), + Err: errForPrint, ClientErr: rosettaErr, Retry: ((rosettaErr != nil && rosettaErr.Retriable) || transientError(err) || f.forceRetry) && !errors.Is(err, context.Canceled), diff --git a/fetcher/fetcher.go b/fetcher/fetcher.go index 114645de..b1e304df 100644 --- a/fetcher/fetcher.go +++ b/fetcher/fetcher.go @@ -22,6 +22,7 @@ import ( "net/http" "time" + "github.com/fatih/color" "golang.org/x/sync/semaphore" "github.com/coinbase/rosetta-sdk-go/asserter" @@ -75,6 +76,7 @@ type Fetcher struct { insecureTLS bool forceRetry bool httpTimeout time.Duration + metaData string // connectionSemaphore is used to limit the // number of concurrent requests we make. @@ -155,6 +157,7 @@ func (f *Fetcher) InitializeAsserter( *Error, ) { if f.Asserter != nil { + color.Red("asserter already initialized%s", f.metaData) return nil, nil, &Error{Err: errors.New("asserter already initialized")} } diff --git a/parser/exemptions.go b/parser/exemptions.go index 645da2d5..7ad28363 100644 --- a/parser/exemptions.go +++ b/parser/exemptions.go @@ -51,7 +51,7 @@ func MatchBalanceExemption( matchedExemptions []*types.BalanceExemption, difference string, // live - computed ) *types.BalanceExemption { - bigDifference, ok := new(big.Int).SetString(difference, 10) + bigDifference, ok := new(big.Int).SetString(difference, 10) // nolint if !ok { return nil } diff --git a/reconciler/configuration.go b/reconciler/configuration.go index 3472d3fa..940d67cb 100644 --- a/reconciler/configuration.go +++ b/reconciler/configuration.go @@ -110,3 +110,10 @@ func WithBacklogSize(size int) Option { r.backlogSize = size } } + +// add a metaData map to fetcher +func WithMetaData(metaData string) Option { + return func(r *Reconciler) { + r.metaData = metaData + } +} diff --git a/reconciler/types.go b/reconciler/types.go index f383a165..c36d019b 100644 --- a/reconciler/types.go +++ b/reconciler/types.go @@ -312,4 +312,7 @@ type Reconciler struct { // blocks asynchronously so that we don't slow down the sync // loop. processQueue chan *blockRequest + + // store customized data + metaData string } diff --git a/server/api.go b/server/api.go index f8d45265..2d20162d 100644 --- a/server/api.go +++ b/server/api.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_account.go b/server/api_account.go index 508d8664..3a98b425 100644 --- a/server/api_account.go +++ b/server/api_account.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_block.go b/server/api_block.go index 0356a257..b6f047ad 100644 --- a/server/api_block.go +++ b/server/api_block.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_call.go b/server/api_call.go index 69877c76..66ee825c 100644 --- a/server/api_call.go +++ b/server/api_call.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_construction.go b/server/api_construction.go index 7b000f1a..c7421f61 100644 --- a/server/api_construction.go +++ b/server/api_construction.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_events.go b/server/api_events.go index e2581e25..73592970 100644 --- a/server/api_events.go +++ b/server/api_events.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_mempool.go b/server/api_mempool.go index 7388a19c..54f1d8d0 100644 --- a/server/api_mempool.go +++ b/server/api_mempool.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_network.go b/server/api_network.go index fa32fcc9..82c2c911 100644 --- a/server/api_network.go +++ b/server/api_network.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/api_search.go b/server/api_search.go index d1f70bfd..d755c309 100644 --- a/server/api_search.go +++ b/server/api_search.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/logger.go b/server/logger.go index df9beab0..33bb86e5 100644 --- a/server/logger.go +++ b/server/logger.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/routers.go b/server/routers.go index 71523150..99d5456c 100644 --- a/server/routers.go +++ b/server/routers.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/statefulsyncer/configuration.go b/statefulsyncer/configuration.go index de1e37a0..b667403d 100644 --- a/statefulsyncer/configuration.go +++ b/statefulsyncer/configuration.go @@ -66,3 +66,10 @@ func WithSeenConcurrency(concurrency int64) Option { s.seenSemaphoreSize = concurrency } } + +// add a metaData map to fetcher +func WithMetaData(metaData string) Option { + return func(s *StatefulSyncer) { + s.metaData = metaData + } +} diff --git a/statefulsyncer/stateful_syncer.go b/statefulsyncer/stateful_syncer.go index fa4de596..9a9d2f93 100644 --- a/statefulsyncer/stateful_syncer.go +++ b/statefulsyncer/stateful_syncer.go @@ -22,6 +22,7 @@ import ( "runtime" "time" + "github.com/fatih/color" "golang.org/x/sync/semaphore" "github.com/coinbase/rosetta-sdk-go/fetcher" @@ -72,6 +73,8 @@ type StatefulSyncer struct { // BlockSeen occur concurrently. seenSemaphore *semaphore.Weighted seenSemaphoreSize int64 + // store customized metaData + metaData string } // Logger is used by the statefulsyncer to @@ -142,7 +145,9 @@ func (s *StatefulSyncer) Sync(ctx context.Context, startIndex int64, endIndex in // Ensure storage is in correct state for starting at index if startIndex != -1 { // attempt to remove blocks from storage (without handling) if err := s.blockStorage.SetNewStartIndex(ctx, startIndex); err != nil { - return fmt.Errorf("unable to set new start index %d: %w", startIndex, err) + err = fmt.Errorf("unable to set new start index %d: %w%s", startIndex, err, s.metaData) + color.Red(err.Error()) + return err } } else { // attempt to load last processed index head, err := s.blockStorage.GetHeadBlockIdentifier(ctx) @@ -166,6 +171,7 @@ func (s *StatefulSyncer) Sync(ctx context.Context, startIndex int64, endIndex in syncer.WithCacheSize(s.cacheSize), syncer.WithMaxConcurrency(s.maxConcurrency), syncer.WithAdjustmentWindow(s.adjustmentWindow), + syncer.WithMetaData(s.metaData), ) return syncer.Sync(ctx, startIndex, endIndex) @@ -183,7 +189,9 @@ func (s *StatefulSyncer) Prune(ctx context.Context, helper PruneHelper) error { // as the time between pruning runs. Using a timer would only guarantee // that the difference between starts of each pruning run are s.pruneSleepTime. if err := utils.ContextSleep(ctx, s.pruneSleepTime); err != nil { - return fmt.Errorf("context is canceled during context sleep: %w", err) + err = fmt.Errorf("context is canceled during context sleep: %w%s", err, s.metaData) + color.Red(err.Error()) + return err } headBlock, err := s.blockStorage.GetHeadBlockIdentifier(ctx) @@ -192,7 +200,9 @@ func (s *StatefulSyncer) Prune(ctx context.Context, helper PruneHelper) error { continue } if err != nil { - return fmt.Errorf("failed to get head block: %w", err) + err = fmt.Errorf("failed to get head block: %w%s", err, s.metaData) + color.Red(err.Error()) + return err } oldestIndex, err := s.blockStorage.GetOldestBlockIndex(ctx) @@ -201,12 +211,16 @@ func (s *StatefulSyncer) Prune(ctx context.Context, helper PruneHelper) error { continue } if err != nil { - return fmt.Errorf("failed to get the oldest block index: %w", err) + err = fmt.Errorf("failed to get the oldest block index: %w%s", err, s.metaData) + color.Red(err.Error()) + return err } pruneableIndex, err := helper.PruneableIndex(ctx, headBlock.Index) if err != nil { - return fmt.Errorf("could not determine pruneable index: %w", err) + err = fmt.Errorf("could not determine pruneable index: %w%s", err, s.metaData) + color.Red(err.Error()) + return err } if pruneableIndex < oldestIndex { @@ -219,7 +233,14 @@ func (s *StatefulSyncer) Prune(ctx context.Context, helper PruneHelper) error { int64(s.pastBlockLimit)*pruneBuffer, // we should be very cautious about pruning ) if err != nil { - return fmt.Errorf("failed to prune with pruneable index %d: %w", pruneableIndex, err) + err = fmt.Errorf( + "failed to prune with pruneable index %d: %w%s", + pruneableIndex, + err, + s.metaData, + ) + color.Red(err.Error()) + return err } // firstPruned and lastPruned are -1 if there is nothing to prune @@ -228,7 +249,7 @@ func (s *StatefulSyncer) Prune(ctx context.Context, helper PruneHelper) error { if firstPruned == lastPruned { pruneMessage = fmt.Sprintf("pruned block %d", firstPruned) } - + color.Cyan("%s%s", pruneMessage, s.metaData) log.Println(pruneMessage) } } @@ -244,12 +265,15 @@ func (s *StatefulSyncer) BlockSeen(ctx context.Context, block *types.Block) erro defer s.seenSemaphore.Release(semaphoreWeight) if err := s.blockStorage.SeeBlock(ctx, block); err != nil { - return fmt.Errorf( - "unable to pre-store block %d (block hash: %s): %w", + err = fmt.Errorf( + "unable to pre-store block %d (block hash: %s): %w%s", block.BlockIdentifier.Index, block.BlockIdentifier.Hash, err, + s.metaData, ) + color.Red(err.Error()) + return err } return nil @@ -259,12 +283,15 @@ func (s *StatefulSyncer) BlockSeen(ctx context.Context, block *types.Block) erro func (s *StatefulSyncer) BlockAdded(ctx context.Context, block *types.Block) error { err := s.blockStorage.AddBlock(ctx, block) if err != nil { - return fmt.Errorf( - "unable to add block %d (block hash: %s) to storage: %w", + err = fmt.Errorf( + "unable to add block %d (block hash: %s) to storage: %w%s", block.BlockIdentifier.Index, block.BlockIdentifier.Hash, err, + s.metaData, ) + color.Red(err.Error()) + return err } _ = s.logger.AddBlockStream(ctx, block) @@ -278,12 +305,15 @@ func (s *StatefulSyncer) BlockRemoved( ) error { err := s.blockStorage.RemoveBlock(ctx, blockIdentifier) if err != nil { - return fmt.Errorf( - "unable to remove block %d (block hash: %s) from storage: %w", + err = fmt.Errorf( + "unable to remove block %d (block hash: %s) from storage: %w%s", blockIdentifier.Index, blockIdentifier.Hash, err, + s.metaData, ) + color.Red(err.Error()) + return err } _ = s.logger.RemoveBlockStream(ctx, blockIdentifier) @@ -298,11 +328,14 @@ func (s *StatefulSyncer) NetworkStatus( ) (*types.NetworkStatusResponse, error) { networkStatus, fetchErr := s.fetcher.NetworkStatusRetry(ctx, network, nil) if fetchErr != nil { - return nil, fmt.Errorf( - "failed to get network status of %s with retry: %w", + errForPrint := fmt.Errorf( + "failed to get network status of %s with retry: %w%s", network.Network, fetchErr.Err, + s.metaData, ) + color.Red(errForPrint.Error()) + return nil, errForPrint } return networkStatus, nil @@ -316,12 +349,15 @@ func (s *StatefulSyncer) Block( ) (*types.Block, error) { blockResponse, fetchErr := s.fetcher.BlockRetry(ctx, network, block) if fetchErr != nil { - return nil, fmt.Errorf( - "unable to fetch block %d from network %s with retry: %w", + errForPrint := fmt.Errorf( + "unable to fetch block %d from network %s with retry: %w%s", *block.Index, network.Network, fetchErr.Err, + s.metaData, ) + color.Red(errForPrint.Error()) + return nil, errForPrint } return blockResponse, nil } diff --git a/storage/database/badger_database.go b/storage/database/badger_database.go index 4325ca56..70adaff3 100644 --- a/storage/database/badger_database.go +++ b/storage/database/badger_database.go @@ -30,6 +30,7 @@ import ( "github.com/dgraph-io/badger/v2" "github.com/dgraph-io/badger/v2/options" + "github.com/fatih/color" "github.com/coinbase/rosetta-sdk-go/storage/encoder" storageErrs "github.com/coinbase/rosetta-sdk-go/storage/errors" @@ -100,6 +101,8 @@ type BadgerDatabase struct { writer *utils.MutexMap writerShards int + metaData string + // Track the closed status to ensure we exit garbage // collection when the db closes. closed chan struct{} @@ -262,13 +265,17 @@ func NewBadgerDatabase( db, err := badger.Open(b.badgerOptions) if err != nil { - return nil, fmt.Errorf("unable to open database: %w", err) + err = fmt.Errorf("unable to open database: %w%s", err, b.metaData) + color.Red(err.Error()) + return nil, err } b.db = db encoder, err := encoder.NewEncoder(b.compressorEntries, b.pool, b.compress) if err != nil { - return nil, fmt.Errorf("unable to load compressor: %w", err) + err = fmt.Errorf("unable to load compressor: %w%s", err, b.metaData) + color.Red(err.Error()) + return nil, err } b.encoder = encoder @@ -286,7 +293,9 @@ func (b *BadgerDatabase) Close(ctx context.Context) error { close(b.closed) if err := b.db.Close(); err != nil { - return fmt.Errorf("unable to close badger database: %w", err) + err = fmt.Errorf("unable to close badger database: %w%s", err, b.metaData) + color.Red(err.Error()) + return err } return nil @@ -326,11 +335,19 @@ func (b *BadgerDatabase) periodicGC(ctx context.Context) { // collected. We should sleep instead of waiting // the full GC collection interval to see if there // is anything else to collect. - log.Printf("successful value log garbage collection (%s)", time.Since(start)) + msg := fmt.Sprintf( + "successful value log garbage collection (%s)%s", + time.Since(start), + b.metaData, + ) + color.Cyan(msg) + log.Print(msg) gcTimeout.Reset(defaultGCSleep) default: // Not much we can do on a random error but log it and continue. - log.Printf("error during a GC cycle: %s\n", err.Error()) + msg := fmt.Sprintf("error during a GC cycle: %s%s\n", err.Error(), b.metaData) + color.Cyan(msg) + log.Print(msg) gcTimeout.Reset(defaultGCInterval) } } @@ -436,7 +453,9 @@ func (b *BadgerTransaction) Commit(context.Context) error { b.releaseLocks() if err != nil { - return fmt.Errorf("unable to commit transaction: %w", err) + err = fmt.Errorf("unable to commit transaction: %w%s", err, b.db.metaData) + color.Red(err.Error()) + return err } return nil @@ -494,7 +513,9 @@ func (b *BadgerTransaction) Get( if err == badger.ErrKeyNotFound { return false, nil, nil } else if err != nil { - return false, nil, fmt.Errorf("unable to get the item of key %s within a transaction: %w", string(key), err) + err = fmt.Errorf("unable to get the item of key %s within a transaction: %w%s", string(key), err, b.db.metaData) + color.Red(err.Error()) + return false, nil, err } err = item.Value(func(v []byte) error { @@ -502,11 +523,14 @@ func (b *BadgerTransaction) Get( return err }) if err != nil { - return false, nil, fmt.Errorf( - "unable to get the value from the item for key %s: %w", + err = fmt.Errorf( + "unable to get the value from the item for key %s: %w%s", string(key), err, + b.db.metaData, ) + color.Red(err.Error()) + return false, nil, err } return true, value.Bytes(), nil @@ -543,22 +567,34 @@ func (b *BadgerTransaction) Scan( k := item.Key() err := item.Value(func(v []byte) error { if err := worker(k, v); err != nil { - return fmt.Errorf("worker failed for key %s: %w", string(k), err) + err = fmt.Errorf("worker failed for key %s: %w%s", string(k), err, b.db.metaData) + color.Red(err.Error()) + return err } return nil }) if err != nil { - return -1, fmt.Errorf( - "unable to get the value from the item for key %s: %w", + err = fmt.Errorf( + "unable to get the value from the item for key %s: %w%s", string(k), err, + b.db.metaData, ) + color.Red(err.Error()) + return -1, err } entries++ if logEntries && entries%logModulo == 0 { - log.Printf("scanned %d entries for %s\n", entries, string(prefix)) + msg := fmt.Sprintf( + "scanned %d entries for %s%s\n", + entries, + string(prefix), + b.db.metaData, + ) + color.Cyan(msg) + log.Print(msg) } } @@ -600,6 +636,11 @@ func decompressAndSave( return float64(len(decompressed)), float64(len(v)), nil } +// GetInfo returns customized metaData for db's metaData +func (b *BadgerDatabase) GetMetaData() string { + return b.metaData +} + func decompressAndEncode( path string, namespace string, diff --git a/storage/database/badger_database_configuration.go b/storage/database/badger_database_configuration.go index 0a746123..b27f27df 100644 --- a/storage/database/badger_database_configuration.go +++ b/storage/database/badger_database_configuration.go @@ -54,7 +54,7 @@ func WithIndexCacheSize(size int64) BadgerOption { // WithTableSize override the MaxTableSize // setting for the BadgerDB. The size here is in GB. func WithTableSize(size int64) BadgerOption { - size = size << 30 + size = size << 30 // nolint return func(b *BadgerDatabase) { b.badgerOptions.MaxTableSize = size } @@ -63,7 +63,7 @@ func WithTableSize(size int64) BadgerOption { // WithTableSize override the ValueLogFileSize // setting for the BadgerDB. The size here is in MB. func WithValueLogFileSize(size int64) BadgerOption { - size = size << 20 + size = size << 20 // nolint return func(b *BadgerDatabase) { b.badgerOptions.ValueLogFileSize = size } @@ -86,3 +86,10 @@ func WithWriterShards(shards int) BadgerOption { b.writerShards = shards } } + +// add a info map to BadgerDatabase +func WithMetaData(metaData string) BadgerOption { + return func(b *BadgerDatabase) { + b.metaData = metaData + } +} diff --git a/storage/database/database.go b/storage/database/database.go index 4a8f4bc3..4bef5a08 100644 --- a/storage/database/database.go +++ b/storage/database/database.go @@ -48,6 +48,9 @@ type Database interface { // in the database. This *Encoder often performs some // form of compression on data. Encoder() *encoder.Encoder + + // GetMetaData returns customized metaData for db's metaData + GetMetaData() string } // Transaction is an interface that provides diff --git a/storage/modules/balance_storage.go b/storage/modules/balance_storage.go index 9261fe45..a7f6813c 100644 --- a/storage/modules/balance_storage.go +++ b/storage/modules/balance_storage.go @@ -376,7 +376,7 @@ func (b *BalanceStorage) SetBalance( // Set current balance key = GetAccountKey(balanceNamespace, account, amount.Currency) - value, ok := new(big.Int).SetString(amount.Value, 10) + value, ok := new(big.Int).SetString(amount.Value, 10) // nolint if !ok { return storageErrs.ErrInvalidValue } @@ -775,7 +775,7 @@ func (b *BalanceStorage) OrphanBalance( return false, storageErrs.ErrAccountMissing } - difference, ok := new(big.Int).SetString(change.Difference, 10) + difference, ok := new(big.Int).SetString(change.Difference, 10) // nolint if !ok { return false, storageErrs.ErrInvalidChangeValue } @@ -877,7 +877,7 @@ func (b *BalanceStorage) UpdateBalance( return false, fmt.Errorf("unable to apply exemptions: %w", err) } - bigNewVal, ok := new(big.Int).SetString(newVal, 10) + bigNewVal, ok := new(big.Int).SetString(newVal, 10) // nolint if !ok { return false, fmt.Errorf("%s is not an integer", newVal) } @@ -1183,7 +1183,7 @@ func (b *BalanceStorage) BootstrapBalances( dbTransaction = b.db.Transaction(ctx) } // Ensure change.Difference is valid - amountValue, ok := new(big.Int).SetString(balance.Value, 10) + amountValue, ok := new(big.Int).SetString(balance.Value, 10) // nolint if !ok { return fmt.Errorf("%s is not an integer", balance.Value) } diff --git a/storage/modules/coin_storage.go b/storage/modules/coin_storage.go index cd9255c0..3882f39e 100644 --- a/storage/modules/coin_storage.go +++ b/storage/modules/coin_storage.go @@ -514,7 +514,7 @@ func (c *CoinStorage) GetLargestCoin( continue } - val, ok := new(big.Int).SetString(coin.Amount.Value, 10) + val, ok := new(big.Int).SetString(coin.Amount.Value, 10) // nolint if !ok { return nil, nil, nil, fmt.Errorf( "coin %s is invalid: %w", diff --git a/syncer/configuration.go b/syncer/configuration.go index cd63664c..de631f63 100644 --- a/syncer/configuration.go +++ b/syncer/configuration.go @@ -65,3 +65,10 @@ func WithAdjustmentWindow(adjustmentWindow int64) Option { s.adjustmentWindow = adjustmentWindow } } + +// add a info map to Syncer +func WithMetaData(metaData string) Option { + return func(s *Syncer) { + s.metaData = metaData + } +} diff --git a/syncer/syncer.go b/syncer/syncer.go index 743b1805..6679e5b6 100644 --- a/syncer/syncer.go +++ b/syncer/syncer.go @@ -21,6 +21,7 @@ import ( "log" "time" + "github.com/fatih/color" "golang.org/x/sync/errgroup" "github.com/coinbase/rosetta-sdk-go/types" @@ -67,7 +68,14 @@ func (s *Syncer) setStart( s.network, ) if err != nil { - return fmt.Errorf("unable to get network status of %s: %w", s.network.Network, err) + err = fmt.Errorf( + "unable to get network status of %s: %w%s", + s.network.Network, + err, + s.metaData, + ) + color.Red(err.Error()) + return err } s.genesisBlock = networkStatus.GenesisBlockIdentifier @@ -99,11 +107,14 @@ func (s *Syncer) nextSyncableRange( s.network, ) if err != nil { - return -1, false, fmt.Errorf( - "unable to get network status of %s: %w", + err = fmt.Errorf( + "unable to get network status of %s: %w%s", s.network.Network, err, + s.metaData, ) + color.Red(err.Error()) + return -1, false, err } // Update the syncer's known tip @@ -145,12 +156,15 @@ func (s *Syncer) checkRemove( // Ensure processing correct index block := br.block if block.BlockIdentifier.Index != s.nextIndex { - return false, nil, fmt.Errorf( - "expected block index %d, but got %d: %w", + errForPrint := fmt.Errorf( + "expected block index %d, but got %d: %w%s", s.nextIndex, block.BlockIdentifier.Index, ErrOutOfOrder, + s.metaData, ) + color.Red(errForPrint.Error()) + return false, nil, errForPrint } // Check if block parent is head @@ -177,21 +191,27 @@ func (s *Syncer) processBlock( shouldRemove, lastBlock, err := s.checkRemove(br) if err != nil { - return fmt.Errorf( - "failed to check if the last block should be removed when processing block %d: %w", + err = fmt.Errorf( + "failed to check if the last block should be removed when processing block %d: %w%s", br.index, err, + s.metaData, ) + color.Red(err.Error()) + return err } if shouldRemove { err = s.handler.BlockRemoved(ctx, lastBlock) if err != nil { - return fmt.Errorf( - "failed to handle the event of block %d is removed: %w", + err = fmt.Errorf( + "failed to handle the event of block %d is removed: %w%s", lastBlock.Index, err, + s.metaData, ) + color.Red(err.Error()) + return err } s.pastBlocks = s.pastBlocks[:len(s.pastBlocks)-1] s.nextIndex = lastBlock.Index @@ -201,11 +221,14 @@ func (s *Syncer) processBlock( block := br.block err = s.handler.BlockAdded(ctx, block) if err != nil { - return fmt.Errorf( - "failed to handle the event of block %d is added: %w", + err = fmt.Errorf( + "failed to handle the event of block %d is added: %w%s", block.BlockIdentifier.Index, err, + s.metaData, ) + color.Red(err.Error()) + return err } s.pastBlocks = append(s.pastBlocks, block.BlockIdentifier) @@ -278,13 +301,22 @@ func (s *Syncer) fetchBlockResult( case errors.Is(err, ErrOrphanHead): br.orphanHead = true case err != nil: - return nil, fmt.Errorf("unable to fetch block %d: %w", index, err) + err = fmt.Errorf("unable to fetch block %d: %w%s", index, err, s.metaData) + color.Red(err.Error()) + return nil, err default: br.block = block } if err := s.handleSeenBlock(ctx, br); err != nil { - return nil, fmt.Errorf("failed to handle the event of block %d is seen: %w", br.index, err) + err = fmt.Errorf( + "failed to handle the event of block %d is seen: %w%s", + br.index, + err, + s.metaData, + ) + color.Red(err.Error()) + return nil, err } return br, nil @@ -318,7 +350,9 @@ func (s *Syncer) fetchBlocks( b, ) if err != nil { - return s.safeExit(fmt.Errorf("unable to fetch block %d: %w", b, err)) + err = fmt.Errorf("unable to fetch block %d: %w%s", b, err, s.metaData) + color.Red(err.Error()) + return s.safeExit(err) } select { @@ -374,7 +408,14 @@ func (s *Syncer) processBlocks( s.nextIndex, ) if err != nil { - return fmt.Errorf("unable to fetch block %d during re-org: %w", s.nextIndex, err) + err = fmt.Errorf( + "unable to fetch block %d during re-org: %w%s", + s.nextIndex, + err, + s.metaData, + ) + color.Red(err.Error()) + return err } } else { // Anytime we re-fetch an index, we @@ -435,11 +476,14 @@ func (s *Syncer) adjustWorkers() bool { s.concurrency++ s.lastAdjustment = 0 shouldCreate = true - log.Printf( - "increasing syncer concurrency to %d (projected new cache size: %f MB)\n", + msg := fmt.Sprintf( + "increasing syncer concurrency to %d (projected new cache size: %f MB%s)\n", s.goalConcurrency, utils.BtoMb(max*float64(s.goalConcurrency)), + s.metaData, ) + color.Cyan(msg) + log.Print(msg) } // If >= cacheSize, decrease concurrency however many necessary to fit max cache size. @@ -455,11 +499,14 @@ func (s *Syncer) adjustWorkers() bool { if s.goalConcurrency != newGoalConcurrency { s.goalConcurrency = newGoalConcurrency s.lastAdjustment = 0 - log.Printf( - "reducing syncer concurrency to %d (projected new cache size: %f MB)\n", + msg := fmt.Sprintf( + "reducing syncer concurrency to %d (projected new cache size: %f MB%s)\n", s.goalConcurrency, utils.BtoMb(max*float64(s.goalConcurrency)), + s.metaData, ) + color.Cyan(msg) + log.Print(msg) } } @@ -499,7 +546,15 @@ func (s *Syncer) sequenceBlocks( // nolint:golint cache[result.index] = result if err := s.processBlocks(ctx, cache, endIndex); err != nil { - return fmt.Errorf("unable to process block range %d-%d: %w", s.nextIndex, endIndex, err) + err = fmt.Errorf( + "unable to process block range %d-%d: %w%s", + s.nextIndex, + endIndex, + err, + s.metaData, + ) + color.Red(err.Error()) + return err } // Determine if concurrency should be adjusted. @@ -605,11 +660,21 @@ func (s *Syncer) syncRange( fetchedBlocks, endIndex, ); err != nil { - return fmt.Errorf("failed to sequence block range %d-%d: %w", s.nextIndex, endIndex, err) + err = fmt.Errorf( + "failed to sequence block range %d-%d: %w%s", + s.nextIndex, + endIndex, + err, + s.metaData, + ) + color.Red(err.Error()) + return err } if err := g.Wait(); err != nil { - return fmt.Errorf("unable to sync to %d: %w", endIndex, err) + err = fmt.Errorf("unable to sync to %d: %w%s", endIndex, err, s.metaData) + color.Red(err.Error()) + return err } return nil @@ -635,7 +700,9 @@ func (s *Syncer) Sync( endIndex int64, ) error { if err := s.setStart(ctx, startIndex); err != nil { - return fmt.Errorf("unable to set start index %d: %w", startIndex, err) + err = fmt.Errorf("unable to set start index %d: %w%s", startIndex, err, s.metaData) + color.Red(err.Error()) + return err } for { @@ -644,7 +711,9 @@ func (s *Syncer) Sync( endIndex, ) if err != nil { - return fmt.Errorf("unable to get next syncable range: %w", err) + err = fmt.Errorf("unable to get next syncable range: %w%s", err, s.metaData) + color.Red(err.Error()) + return err } if halt { @@ -657,14 +726,20 @@ func (s *Syncer) Sync( } if s.nextIndex != rangeEnd { - log.Printf("Syncing %d-%d\n", s.nextIndex, rangeEnd) + msg := fmt.Sprintf("Syncing %d-%d%s\n", s.nextIndex, rangeEnd, s.metaData) + color.Cyan(msg) + log.Print(msg) } else { - log.Printf("Syncing %d\n", s.nextIndex) + msg := fmt.Sprintf("Syncing %d%s\n", s.nextIndex, s.metaData) + color.Cyan(msg) + log.Print(msg) } err = s.syncRange(ctx, rangeEnd) if err != nil { - return fmt.Errorf("unable to sync to %d: %w", rangeEnd, err) + err = fmt.Errorf("unable to sync to %d: %w%s", rangeEnd, err, s.metaData) + color.Red(err.Error()) + return err } if ctx.Err() != nil { @@ -677,6 +752,8 @@ func (s *Syncer) Sync( } s.cancel() - log.Printf("Finished syncing %d-%d\n", startIndex, endIndex) + msg := fmt.Sprintf("Finished syncing %d-%d%s\n", startIndex, endIndex, s.metaData) + color.Cyan(msg) + log.Print(msg) return nil } diff --git a/syncer/types.go b/syncer/types.go index fc06421a..dbb35bfa 100644 --- a/syncer/types.go +++ b/syncer/types.go @@ -158,6 +158,9 @@ type Syncer struct { adjustmentWindow int64 concurrencyLock sync.Mutex + // store customized info + metaData string + // doneLoading is used to coordinate adding goroutines // when close to the end of syncing a range. doneLoading bool diff --git a/types/account_balance_request.go b/types/account_balance_request.go index 52a4b785..3a44d8ac 100644 --- a/types/account_balance_request.go +++ b/types/account_balance_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/account_balance_response.go b/types/account_balance_response.go index 97562564..539b59c9 100644 --- a/types/account_balance_response.go +++ b/types/account_balance_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/account_coins_request.go b/types/account_coins_request.go index ed2b996f..7087b76e 100644 --- a/types/account_coins_request.go +++ b/types/account_coins_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/account_coins_response.go b/types/account_coins_response.go index 4c6f601a..cab26325 100644 --- a/types/account_coins_response.go +++ b/types/account_coins_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/account_identifier.go b/types/account_identifier.go index 07a11dff..fe5a8361 100644 --- a/types/account_identifier.go +++ b/types/account_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/allow.go b/types/allow.go index ee6804a9..b8c49423 100644 --- a/types/allow.go +++ b/types/allow.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/amount.go b/types/amount.go index 42af1d81..b940f7de 100644 --- a/types/amount.go +++ b/types/amount.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/balance_exemption.go b/types/balance_exemption.go index 60219f4a..68225a4b 100644 --- a/types/balance_exemption.go +++ b/types/balance_exemption.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block.go b/types/block.go index 2d23d22c..97d8755b 100644 --- a/types/block.go +++ b/types/block.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_event.go b/types/block_event.go index d67526de..bfcf134f 100644 --- a/types/block_event.go +++ b/types/block_event.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_event_type.go b/types/block_event_type.go index d61515b2..e67429be 100644 --- a/types/block_event_type.go +++ b/types/block_event_type.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_identifier.go b/types/block_identifier.go index 32688aaa..f3da3b8b 100644 --- a/types/block_identifier.go +++ b/types/block_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_request.go b/types/block_request.go index e79cefe0..b56f797f 100644 --- a/types/block_request.go +++ b/types/block_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_response.go b/types/block_response.go index faf7bab9..fd66e59a 100644 --- a/types/block_response.go +++ b/types/block_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_transaction.go b/types/block_transaction.go index b1124b54..e577260d 100644 --- a/types/block_transaction.go +++ b/types/block_transaction.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_transaction_request.go b/types/block_transaction_request.go index ce231610..ba50d706 100644 --- a/types/block_transaction_request.go +++ b/types/block_transaction_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/block_transaction_response.go b/types/block_transaction_response.go index effa9114..5b518150 100644 --- a/types/block_transaction_response.go +++ b/types/block_transaction_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/call_request.go b/types/call_request.go index ae319fa7..ae35f2a3 100644 --- a/types/call_request.go +++ b/types/call_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/call_response.go b/types/call_response.go index 35de8dc4..d4cc0e26 100644 --- a/types/call_response.go +++ b/types/call_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/case.go b/types/case.go index 9717780a..551b88b4 100644 --- a/types/case.go +++ b/types/case.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/coin.go b/types/coin.go index 88c90779..3e22ab6a 100644 --- a/types/coin.go +++ b/types/coin.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/coin_action.go b/types/coin_action.go index 684b7ff0..17ea972c 100644 --- a/types/coin_action.go +++ b/types/coin_action.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/coin_change.go b/types/coin_change.go index 15059e94..d9089dd1 100644 --- a/types/coin_change.go +++ b/types/coin_change.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/coin_identifier.go b/types/coin_identifier.go index eda22622..81f8c4ce 100644 --- a/types/coin_identifier.go +++ b/types/coin_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_combine_request.go b/types/construction_combine_request.go index dfa6814a..f55277bd 100644 --- a/types/construction_combine_request.go +++ b/types/construction_combine_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_combine_response.go b/types/construction_combine_response.go index 9677b59b..3de1e9eb 100644 --- a/types/construction_combine_response.go +++ b/types/construction_combine_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_derive_request.go b/types/construction_derive_request.go index 86164cca..0fa06eeb 100644 --- a/types/construction_derive_request.go +++ b/types/construction_derive_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_hash_request.go b/types/construction_hash_request.go index 839f15f5..59887fb8 100644 --- a/types/construction_hash_request.go +++ b/types/construction_hash_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_metadata_request.go b/types/construction_metadata_request.go index d8a2ea83..f20f734c 100644 --- a/types/construction_metadata_request.go +++ b/types/construction_metadata_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_metadata_response.go b/types/construction_metadata_response.go index 52427841..a9515550 100644 --- a/types/construction_metadata_response.go +++ b/types/construction_metadata_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_parse_request.go b/types/construction_parse_request.go index 527b0619..65f978cb 100644 --- a/types/construction_parse_request.go +++ b/types/construction_parse_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_payloads_request.go b/types/construction_payloads_request.go index aa1afa44..a6f018b9 100644 --- a/types/construction_payloads_request.go +++ b/types/construction_payloads_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_payloads_response.go b/types/construction_payloads_response.go index ea69d477..3747ab79 100644 --- a/types/construction_payloads_response.go +++ b/types/construction_payloads_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_preprocess_request.go b/types/construction_preprocess_request.go index 3867dabc..764097cf 100644 --- a/types/construction_preprocess_request.go +++ b/types/construction_preprocess_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_preprocess_response.go b/types/construction_preprocess_response.go index 9da81d88..eeb907ea 100644 --- a/types/construction_preprocess_response.go +++ b/types/construction_preprocess_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/construction_submit_request.go b/types/construction_submit_request.go index 2f9bbf7f..8ab30658 100644 --- a/types/construction_submit_request.go +++ b/types/construction_submit_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/currency.go b/types/currency.go index 52ed43d1..93f91dc8 100644 --- a/types/currency.go +++ b/types/currency.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/curve_type.go b/types/curve_type.go index 4100c9c0..d03ea3eb 100644 --- a/types/curve_type.go +++ b/types/curve_type.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/direction.go b/types/direction.go index 2d2746bb..5dba38c5 100644 --- a/types/direction.go +++ b/types/direction.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/error.go b/types/error.go index bf7b6fff..7932215f 100644 --- a/types/error.go +++ b/types/error.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/events_blocks_request.go b/types/events_blocks_request.go index 6a48ef9b..b987ae40 100644 --- a/types/events_blocks_request.go +++ b/types/events_blocks_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/events_blocks_response.go b/types/events_blocks_response.go index 0b8b8954..49a70f8a 100644 --- a/types/events_blocks_response.go +++ b/types/events_blocks_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/exemption_type.go b/types/exemption_type.go index 5410bb02..13f0a61a 100644 --- a/types/exemption_type.go +++ b/types/exemption_type.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/mempool_response.go b/types/mempool_response.go index 80087144..afe553ca 100644 --- a/types/mempool_response.go +++ b/types/mempool_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/mempool_transaction_request.go b/types/mempool_transaction_request.go index 8c6e8de3..89015c21 100644 --- a/types/mempool_transaction_request.go +++ b/types/mempool_transaction_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/mempool_transaction_response.go b/types/mempool_transaction_response.go index 118ef24e..b83c7cd0 100644 --- a/types/mempool_transaction_response.go +++ b/types/mempool_transaction_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/metadata_request.go b/types/metadata_request.go index c06a86b0..abfc95ac 100644 --- a/types/metadata_request.go +++ b/types/metadata_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/network_identifier.go b/types/network_identifier.go index ca825139..078df821 100644 --- a/types/network_identifier.go +++ b/types/network_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/network_list_response.go b/types/network_list_response.go index 6e442e6a..6ec0cff4 100644 --- a/types/network_list_response.go +++ b/types/network_list_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/network_options_response.go b/types/network_options_response.go index 6dd7fec9..63fcafd3 100644 --- a/types/network_options_response.go +++ b/types/network_options_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/network_request.go b/types/network_request.go index 5397b2af..71f002e0 100644 --- a/types/network_request.go +++ b/types/network_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/network_status_response.go b/types/network_status_response.go index 3b9cdb3f..5a02a4bb 100644 --- a/types/network_status_response.go +++ b/types/network_status_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/operation.go b/types/operation.go index 539db4f9..e54c1b7a 100644 --- a/types/operation.go +++ b/types/operation.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/operation_identifier.go b/types/operation_identifier.go index 41787678..be875c24 100644 --- a/types/operation_identifier.go +++ b/types/operation_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/operation_status.go b/types/operation_status.go index c4778d76..f4a29101 100644 --- a/types/operation_status.go +++ b/types/operation_status.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/operator.go b/types/operator.go index 0a952394..70925193 100644 --- a/types/operator.go +++ b/types/operator.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/partial_block_identifier.go b/types/partial_block_identifier.go index 9d8ebd35..9be002aa 100644 --- a/types/partial_block_identifier.go +++ b/types/partial_block_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/peer.go b/types/peer.go index 6b4dedf3..0829720c 100644 --- a/types/peer.go +++ b/types/peer.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/public_key.go b/types/public_key.go index 11fd6122..9cd4d4ab 100644 --- a/types/public_key.go +++ b/types/public_key.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/related_transaction.go b/types/related_transaction.go index 9abe5a14..5f4e7766 100644 --- a/types/related_transaction.go +++ b/types/related_transaction.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/search_transactions_request.go b/types/search_transactions_request.go index 3b1420f8..0d3653de 100644 --- a/types/search_transactions_request.go +++ b/types/search_transactions_request.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/search_transactions_response.go b/types/search_transactions_response.go index 57eda2f7..8881033a 100644 --- a/types/search_transactions_response.go +++ b/types/search_transactions_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/signature.go b/types/signature.go index e96b20b8..e815dd1a 100644 --- a/types/signature.go +++ b/types/signature.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/signature_type.go b/types/signature_type.go index 42cfb1f2..cfa1c360 100644 --- a/types/signature_type.go +++ b/types/signature_type.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/sub_account_identifier.go b/types/sub_account_identifier.go index 78c3c835..dcf32ca9 100644 --- a/types/sub_account_identifier.go +++ b/types/sub_account_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/sub_network_identifier.go b/types/sub_network_identifier.go index 5b4fdb0b..b6880ca5 100644 --- a/types/sub_network_identifier.go +++ b/types/sub_network_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/sync_status.go b/types/sync_status.go index 0015fe86..0124209d 100644 --- a/types/sync_status.go +++ b/types/sync_status.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/transaction.go b/types/transaction.go index ac8a0cf1..5c5d7b15 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/transaction_identifier.go b/types/transaction_identifier.go index 2cd6e233..939abd6f 100644 --- a/types/transaction_identifier.go +++ b/types/transaction_identifier.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/transaction_identifier_response.go b/types/transaction_identifier_response.go index e9113782..93ea9f5f 100644 --- a/types/transaction_identifier_response.go +++ b/types/transaction_identifier_response.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/types.go b/types/types.go index c49f04b3..69d7a6bb 100644 --- a/types/types.go +++ b/types/types.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/types/version.go b/types/version.go index 1f627c23..bbe74e6e 100644 --- a/types/version.go +++ b/types/version.go @@ -1,4 +1,4 @@ -// Copyright 2022 Coinbase, Inc. +// Copyright 2023 Coinbase, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.