Skip to content

Commit

Permalink
Add starknet_subscribeTransactionStatus
Browse files Browse the repository at this point in the history
Co-authored-by: IronGauntlets <[email protected]>
  • Loading branch information
pnowosie and IronGauntlets committed Jan 3, 2025
1 parent c43ebbc commit 62526ce
Show file tree
Hide file tree
Showing 17 changed files with 601 additions and 76 deletions.
22 changes: 20 additions & 2 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@ import (
"github.com/NethermindEth/juno/core/felt"
"github.com/NethermindEth/juno/db"
"github.com/NethermindEth/juno/encoder"
"github.com/NethermindEth/juno/feed"
"github.com/NethermindEth/juno/utils"
"github.com/ethereum/go-ethereum/common"
)

type L1HeadSubscription struct {
*feed.Subscription[*core.L1Head]
}

//go:generate mockgen -destination=../mocks/mock_blockchain.go -package=mocks github.com/NethermindEth/juno/blockchain Reader
type Reader interface {
Height() (height uint64, err error)

Head() (head *core.Block, err error)
L1Head() (*core.L1Head, error)
SubscribeL1Head() L1HeadSubscription
BlockByNumber(number uint64) (block *core.Block, err error)
BlockByHash(hash *felt.Felt) (block *core.Block, err error)

Expand Down Expand Up @@ -81,6 +87,7 @@ type Blockchain struct {
network *utils.Network
database db.DB
listener EventListener
l1HeadFeed *feed.Feed[*core.L1Head]
pendingBlockFn func() *core.Block
}

Expand All @@ -90,6 +97,7 @@ func New(database db.DB, network *utils.Network, pendingBlockFn func() *core.Blo
database: database,
network: network,
listener: &SelectiveListener{},
l1HeadFeed: feed.New[*core.L1Head](),
pendingBlockFn: pendingBlockFn,
}
}
Expand Down Expand Up @@ -279,6 +287,10 @@ func (b *Blockchain) Receipt(hash *felt.Felt) (*core.TransactionReceipt, *felt.F
})
}

func (b *Blockchain) SubscribeL1Head() L1HeadSubscription {
return L1HeadSubscription{b.l1HeadFeed.Subscribe()}
}

func (b *Blockchain) L1Head() (*core.L1Head, error) {
b.listener.OnRead("L1Head")
var update *core.L1Head
Expand All @@ -305,9 +317,15 @@ func (b *Blockchain) SetL1Head(update *core.L1Head) error {
if err != nil {
return err
}
return b.database.Update(func(txn db.Transaction) error {

if err := b.database.Update(func(txn db.Transaction) error {
return txn.Set(db.L1Height.Key(), updateBytes)
})
}); err != nil {
return err
}

Check warning on line 325 in blockchain/blockchain.go

View check run for this annotation

Codecov / codecov/patch

blockchain/blockchain.go#L324-L325

Added lines #L324 - L325 were not covered by tests

b.l1HeadFeed.Send(update)
return nil
}

// Store takes a block and state update and performs sanity checks before putting in the database.
Expand Down
17 changes: 17 additions & 0 deletions blockchain/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,20 @@ func TestL1Update(t *testing.T) {
})
}
}

func TestSubscribeL1Head(t *testing.T) {
l1Head := &core.L1Head{
BlockNumber: 1,
StateRoot: new(felt.Felt).SetUint64(2),
}

chain := blockchain.New(pebble.NewMemTest(t), &utils.Mainnet, nil)
sub := chain.SubscribeL1Head()
t.Cleanup(sub.Unsubscribe)

require.NoError(t, chain.SetL1Head(l1Head))

got, ok := <-sub.Recv()
require.True(t, ok)
assert.Equal(t, l1Head, got)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"finality_status": "RECEIVED",
"status": "this is deprecated",
"block_hash": "0x01010101",
"block_number": 304740,
"transaction_index": 1,
"transaction_hash": "0x1001",
"l2_to_l1_messages": [],
"events": [],
"actual_fee": "0x247aff6e224"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"execution_status": "SUCCEEDED",
"finality_status": "ACCEPTED_ON_L1",
"status": "this is deprecated",
"block_hash": "0x01010101",
"block_number": 304740,
"transaction_index": 1,
"transaction_hash": "0x1010",
"l2_to_l1_messages": [],
"events": [],
"actual_fee": "0x247aff6e224"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"revert_error": "some error",
"execution_status": "REJECTED",
"finality_status": "RECEIVED",
"status": "this is deprecated",
"block_hash": "0x01010101",
"block_number": 304740,
"transaction_index": 1,
"transaction_hash": "0x1111",
"l2_to_l1_messages": [],
"events": [],
"actual_fee": "0x247aff6e224"
}
55 changes: 54 additions & 1 deletion docs/docs/websocket.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,60 @@ When a new block is added, you will receive a message like this:
}
```

## Unsubscribe from newly created blocks
## Subscribe to transaction status changes

The WebSocket server provides a `starknet_subscribeTransactionStatus` method that emits an event when a transaction status changes:

<Tabs>
<TabItem value="request" label="Request">

```json
{
"jsonrpc": "2.0",
"method": "starknet_subscribeTransactionStatus",
"params": [
{
"transaction_hash": "0x631333277e88053336d8c302630b4420dc3ff24018a1c464da37d5e36ea19df"
}
],
"id": 1
}
```

</TabItem>
<TabItem value="response" label="Response">

```json
{
"jsonrpc": "2.0",
"result": 16570962336122680234,
"id": 1
}
```

</TabItem>
</Tabs>

When a transaction get a new status, you will receive a message like this:

```json
{
"jsonrpc": "2.0",
"method": "starknet_subscriptionTransactionsStatus",
"params": {
"result": {
"transaction_hash": "0x631333277e88053336d8c302630b4420dc3ff24018a1c464da37d5e36ea19df",
"status": {
"finality_status": "ACCEPTED_ON_L2",
"execution_status": "SUCCEEDED"
}
},
"subscription_id": 16570962336122680234
}
}
```

## Unsubscribe from previous subscription

Use the `starknet_unsubscribe` method with the `result` value from the subscription response or the `subscription` field from any new block event to stop receiving updates for new blocks:

Expand Down
14 changes: 14 additions & 0 deletions mocks/mock_blockchain.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions mocks/mock_plugin.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 16 additions & 17 deletions mocks/mock_subscriber.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions rpc/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ type EventsArg struct {
ResultPageRequest
}

type SubscriptionID struct {
ID uint64 `json:"subscription_id"`
}

type EventFilter struct {
FromBlock *BlockID `json:"from_block"`
ToBlock *BlockID `json:"to_block"`
Expand Down Expand Up @@ -41,10 +45,6 @@ type EventsChunk struct {
ContinuationToken string `json:"continuation_token,omitempty"`
}

type SubscriptionID struct {
ID uint64 `json:"subscription_id"`
}

/****************************************************
Events Handlers
*****************************************************/
Expand Down
10 changes: 10 additions & 0 deletions rpc/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ type Handler struct {
newHeads *feed.Feed[*core.Header]
reorgs *feed.Feed[*sync.ReorgBlockRange]
pendingTxs *feed.Feed[[]core.Transaction]
l1Heads *feed.Feed[*core.L1Head]

idgen func() uint64
mu stdsync.Mutex // protects subscriptions.
Expand Down Expand Up @@ -138,6 +139,7 @@ func New(bcReader blockchain.Reader, syncReader sync.Reader, virtualMachine vm.V
newHeads: feed.New[*core.Header](),
reorgs: feed.New[*sync.ReorgBlockRange](),
pendingTxs: feed.New[[]core.Transaction](),
l1Heads: feed.New[*core.L1Head](),
subscriptions: make(map[uint64]*subscription),

blockTraceCache: lru.NewCache[traceCacheKey, []TracedBlockTransaction](traceCacheSize),
Expand Down Expand Up @@ -181,12 +183,15 @@ func (h *Handler) Run(ctx context.Context) error {
newHeadsSub := h.syncReader.SubscribeNewHeads().Subscription
reorgsSub := h.syncReader.SubscribeReorg().Subscription
pendingTxsSub := h.syncReader.SubscribePendingTxs().Subscription
l1HeadsSub := h.bcReader.SubscribeL1Head().Subscription
defer newHeadsSub.Unsubscribe()
defer reorgsSub.Unsubscribe()
defer pendingTxsSub.Unsubscribe()
defer l1HeadsSub.Unsubscribe()
feed.Tee(newHeadsSub, h.newHeads)
feed.Tee(reorgsSub, h.reorgs)
feed.Tee(pendingTxsSub, h.pendingTxs)
feed.Tee(l1HeadsSub, h.l1Heads)

<-ctx.Done()
for _, sub := range h.subscriptions {
Expand Down Expand Up @@ -358,6 +363,11 @@ func (h *Handler) Methods() ([]jsonrpc.Method, string) { //nolint: funlen
Params: []jsonrpc.Parameter{{Name: "block", Optional: true}},
Handler: h.SubscribeNewHeads,
},
{
Name: "starknet_subscribeTransactionStatus",
Params: []jsonrpc.Parameter{{Name: "transaction_hash"}, {Name: "block", Optional: true}},
Handler: h.SubscribeTransactionStatus,
},
{
Name: "starknet_subscribePendingTransactions",
Params: []jsonrpc.Parameter{{Name: "transaction_details", Optional: true}, {Name: "sender_address", Optional: true}},
Expand Down
Loading

0 comments on commit 62526ce

Please sign in to comment.