Skip to content

Commit

Permalink
Merge branch 'feature/migrate-to-evm' of github.com:rarimo/evm-aidrop…
Browse files Browse the repository at this point in the history
…-svc into feature/multicall
  • Loading branch information
mhrynenko committed Jun 3, 2024
2 parents 2be4a12 + 2d77f85 commit f3c341d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 7 deletions.
1 change: 1 addition & 0 deletions internal/assets/migrations/001_initial.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CREATE TABLE airdrops
nullifier text NOT NULL,
address text NOT NULL,
tx_hash text,
error text,
amount text NOT NULL,
status tx_status_enum NOT NULL,
created_at timestamp without time zone NOT NULL DEFAULT NOW(),
Expand Down
1 change: 1 addition & 0 deletions internal/data/airdrops.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Airdrop struct {
Nullifier string `db:"nullifier"`
Address string `db:"address"`
TxHash *string `db:"tx_hash"`
Error *string `db:"error"`
Amount string `db:"amount"`
Status string `db:"status"`
CreatedAt time.Time `db:"created_at"`
Expand Down
50 changes: 43 additions & 7 deletions internal/service/broadcaster/broadcaster.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ func (r *Runner) handlePending(ctx context.Context, airdrop data.Airdrop) (err e
defer func() {
r.UnlockNonce()
if err != nil {
r.updateAirdropStatus(ctx, airdrop.ID, txHash, data.TxStatusFailed)
r.updateAirdropStatus(ctx, airdrop.ID, txHash, data.TxStatusFailed, err)
}
}()

r.LockNonce()
r.updateAirdropStatus(ctx, airdrop.ID, txHash, data.TxStatusInProgress)
r.updateAirdropStatus(ctx, airdrop.ID, txHash, data.TxStatusInProgress, nil)

tx, err := r.genTx(ctx, airdrop)
if err != nil {
Expand Down Expand Up @@ -136,32 +136,68 @@ func (r *Runner) waitForTransactionMined(ctx context.Context, transaction *types
go func() {
log.Debugf("waiting to mine")

if _, err := bind.WaitMined(ctx, r.RPC, transaction); err != nil {
receipt, err := bind.WaitMined(ctx, r.RPC, transaction)
if err != nil {
log.WithError(err).WithField("transaction", transaction).Error("failed to wait for mined tx")
r.updateAirdropStatus(ctx, airdrop.ID, transaction.Hash().String(), data.TxStatusFailed)
r.updateAirdropStatus(ctx, airdrop.ID, transaction.Hash().String(), data.TxStatusFailed, err)
}

if receipt.Status != types.ReceiptStatusSuccessful {
txErr, err := r.getTxError(ctx, transaction, r.Address)
if err != nil {
log.WithError(err).WithField("transaction", transaction).Error("failed to get tx error")
r.updateAirdropStatus(ctx, airdrop.ID, transaction.Hash().String(), data.TxStatusFailed, err)
}

log.WithError(err).WithField("transaction", transaction).Error("transaction was mined with failed status")
r.updateAirdropStatus(ctx, airdrop.ID, transaction.Hash().String(), data.TxStatusFailed, txErr)
}

r.updateAirdropStatus(ctx, airdrop.ID, transaction.Hash().String(), data.TxStatusCompleted)
r.updateAirdropStatus(ctx, airdrop.ID, transaction.Hash().String(), data.TxStatusCompleted, nil)

log.Debugf("was mined")
log.Debugf("was mined successfully")
}()
}

func (r *Runner) getTxError(ctx context.Context, tx *types.Transaction, txSender common.Address) (error, error) {
msg := ethereum.CallMsg{
From: txSender,
To: tx.To(),
Gas: tx.Gas(),
GasPrice: tx.GasPrice(),
Value: tx.Value(),
Data: tx.Data(),
}

res, err := r.RPC.CallContract(ctx, msg, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to make call")
}

return errors.New(string(res)), nil
}

// If we don't update tx status from pending, having the successful funds
// transfer, it will be possible to double-spend. With this solution the
// double-spend may still occur, if the service is restarted before the
// successful update. There is a better solution with file creation on context
// cancellation and parsing it on start.
func (r *Runner) updateAirdropStatus(ctx context.Context, id, txHash, status string) {
func (r *Runner) updateAirdropStatus(ctx context.Context, id, txHash, status string, txErr error) {
running.UntilSuccess(ctx, r.log, "tx-status-updater", func(_ context.Context) (bool, error) {
var ptr *string
if txHash != "" {
ptr = &txHash
}

var errMsg *string
if txErr != nil {
msg := txErr.Error()
errMsg = &msg
}
err := r.q.New().Update(id, map[string]any{
"status": status,
"tx_hash": ptr,
"error": errMsg,
})

return err == nil, err
Expand Down

0 comments on commit f3c341d

Please sign in to comment.