@btc-vision/btc-runtime 1.10.8 → 1.10.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +258 -137
  3. package/SECURITY.md +226 -0
  4. package/docs/README.md +614 -0
  5. package/docs/advanced/bitcoin-scripts.md +939 -0
  6. package/docs/advanced/cross-contract-calls.md +579 -0
  7. package/docs/advanced/plugins.md +1006 -0
  8. package/docs/advanced/quantum-resistance.md +660 -0
  9. package/docs/advanced/signature-verification.md +715 -0
  10. package/docs/api-reference/blockchain.md +729 -0
  11. package/docs/api-reference/events.md +642 -0
  12. package/docs/api-reference/op20.md +902 -0
  13. package/docs/api-reference/op721.md +819 -0
  14. package/docs/api-reference/safe-math.md +510 -0
  15. package/docs/api-reference/storage.md +840 -0
  16. package/docs/contracts/op-net-base.md +786 -0
  17. package/docs/contracts/op20-token.md +687 -0
  18. package/docs/contracts/op20s-signatures.md +614 -0
  19. package/docs/contracts/op721-nft.md +785 -0
  20. package/docs/contracts/reentrancy-guard.md +787 -0
  21. package/docs/core-concepts/blockchain-environment.md +724 -0
  22. package/docs/core-concepts/decorators.md +466 -0
  23. package/docs/core-concepts/events.md +652 -0
  24. package/docs/core-concepts/pointers.md +391 -0
  25. package/docs/core-concepts/security.md +473 -0
  26. package/docs/core-concepts/storage-system.md +969 -0
  27. package/docs/examples/basic-token.md +745 -0
  28. package/docs/examples/nft-with-reservations.md +1440 -0
  29. package/docs/examples/oracle-integration.md +1212 -0
  30. package/docs/examples/stablecoin.md +1180 -0
  31. package/docs/getting-started/first-contract.md +575 -0
  32. package/docs/getting-started/installation.md +384 -0
  33. package/docs/getting-started/project-structure.md +630 -0
  34. package/docs/storage/memory-maps.md +764 -0
  35. package/docs/storage/stored-arrays.md +778 -0
  36. package/docs/storage/stored-maps.md +758 -0
  37. package/docs/storage/stored-primitives.md +655 -0
  38. package/docs/types/address.md +773 -0
  39. package/docs/types/bytes-writer-reader.md +938 -0
  40. package/docs/types/calldata.md +744 -0
  41. package/docs/types/safe-math.md +446 -0
  42. package/package.json +52 -27
  43. package/runtime/memory/MapOfMap.ts +1 -0
  44. package/LICENSE.md +0 -21
@@ -0,0 +1,642 @@
1
+ # Events API Reference
2
+
3
+ Events provide a way to emit state change notifications that off-chain applications can monitor.
4
+
5
+ ## Import
6
+
7
+ ```typescript
8
+ import {
9
+ NetEvent,
10
+ TransferredEvent,
11
+ ApprovedEvent,
12
+ MintedEvent,
13
+ BurnedEvent,
14
+ TransferredSingleEvent,
15
+ TransferredBatchEvent,
16
+ ApprovedForAllEvent,
17
+ URIEvent,
18
+ BytesWriter,
19
+ } from '@btc-vision/btc-runtime/runtime';
20
+ ```
21
+
22
+ ## NetEvent Base Class
23
+
24
+ All events extend the `NetEvent` base class.
25
+
26
+ ```typescript
27
+ abstract class NetEvent {
28
+ protected constructor(eventType: string, data: BytesWriter)
29
+ public getEventData(): Uint8Array
30
+ public get length(): u32
31
+ public readonly eventType: string
32
+ }
33
+ ```
34
+
35
+ ## Event Class Hierarchy
36
+
37
+ ```mermaid
38
+ classDiagram
39
+ class NetEvent {
40
+ <<abstract>>
41
+ +string eventType
42
+ #BytesWriter data
43
+ -Uint8Array buffer
44
+ #constructor(eventType: string, data: BytesWriter)
45
+ +getEventData() Uint8Array
46
+ +get length() u32
47
+ }
48
+
49
+ class TransferredEvent {
50
+ +constructor(operator, from, to, amount)
51
+ }
52
+
53
+ class TransferredSingleEvent {
54
+ +constructor(operator, from, to, id, value)
55
+ }
56
+
57
+ class TransferredBatchEvent {
58
+ +constructor(operator, from, to, ids, values)
59
+ }
60
+
61
+ class ApprovedEvent {
62
+ +constructor(owner, spender, amount)
63
+ }
64
+
65
+ class ApprovedForAllEvent {
66
+ +constructor(account, operator, approved)
67
+ }
68
+
69
+ class MintedEvent {
70
+ +constructor(to, amount)
71
+ }
72
+
73
+ class BurnedEvent {
74
+ +constructor(from, amount)
75
+ }
76
+
77
+ class URIEvent {
78
+ +constructor(value, id)
79
+ }
80
+
81
+ class CustomEvent {
82
+ +constructor(...)
83
+ }
84
+
85
+ NetEvent <|-- TransferredEvent
86
+ NetEvent <|-- TransferredSingleEvent
87
+ NetEvent <|-- TransferredBatchEvent
88
+ NetEvent <|-- ApprovedEvent
89
+ NetEvent <|-- ApprovedForAllEvent
90
+ NetEvent <|-- MintedEvent
91
+ NetEvent <|-- BurnedEvent
92
+ NetEvent <|-- URIEvent
93
+ NetEvent <|-- CustomEvent
94
+
95
+ note for NetEvent "All events must extend NetEvent\nand build data in constructor"
96
+ note for CustomEvent "User-defined events\nfor custom contract logic"
97
+ ```
98
+
99
+ ## Creating Custom Events
100
+
101
+ ### Basic Event
102
+
103
+ ```typescript
104
+ @final
105
+ class MyEvent extends NetEvent {
106
+ constructor(value: u256) {
107
+ const data = new BytesWriter(32);
108
+ data.writeU256(value);
109
+ super('MyEvent', data);
110
+ }
111
+ }
112
+
113
+ // Emit
114
+ this.emitEvent(new MyEvent(u256.fromU64(100)));
115
+ ```
116
+
117
+ The following diagram shows the event system architecture:
118
+
119
+ ```mermaid
120
+ graph LR
121
+ subgraph "Event Creation"
122
+ A[Contract Method] -->|Create| B[NetEvent Instance]
123
+ B -->|Extends| C[NetEvent Base Class]
124
+ C --> D[eventType: string]
125
+ C --> E[BytesWriter data]
126
+ end
127
+
128
+ subgraph "Validation"
129
+ E --> F{data.length<br/>352 bytes?}
130
+ F -->|Yes| G[Valid Event]
131
+ F -->|No| H[Revert:<br/>Too Large]
132
+ end
133
+
134
+ subgraph "Emission"
135
+ G --> I[contract.emitEvent]
136
+ I --> J[Blockchain.emit]
137
+ J --> K[Event Binary<br/>Format]
138
+ K --> L[Transaction<br/>Receipt]
139
+ end
140
+ ```
141
+
142
+ ### Multi-Field Event
143
+
144
+ ```typescript
145
+ import { ADDRESS_BYTE_LENGTH, U256_BYTE_LENGTH } from '@btc-vision/btc-runtime/runtime';
146
+
147
+ @final
148
+ class TransferEvent extends NetEvent {
149
+ constructor(from: Address, to: Address, amount: u256) {
150
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + U256_BYTE_LENGTH);
151
+ data.writeAddress(from);
152
+ data.writeAddress(to);
153
+ data.writeU256(amount);
154
+ super('Transfer', data);
155
+ }
156
+ }
157
+ ```
158
+
159
+ ### Event with Data Constructor
160
+
161
+ ```typescript
162
+ @final
163
+ class ComplexEvent extends NetEvent {
164
+ constructor(user: Address, action: u8, timestamp: u64, value: u256) {
165
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH + 1 + 8 + U256_BYTE_LENGTH);
166
+ data.writeAddress(user);
167
+ data.writeU8(action);
168
+ data.writeU64(timestamp);
169
+ data.writeU256(value);
170
+ super('ComplexEvent', data);
171
+ }
172
+ }
173
+ ```
174
+
175
+ ## Predefined Events
176
+
177
+ ### TransferredEvent
178
+
179
+ Standard token transfer event. Event type: `'Transferred'`. Note: OP20 transfers include an operator field.
180
+
181
+ ```typescript
182
+ class TransferredEvent extends NetEvent {
183
+ constructor(
184
+ operator: Address, // The address initiating the transfer
185
+ from: Address, // The sender address
186
+ to: Address, // The recipient address
187
+ amount: u256 // The amount transferred
188
+ )
189
+ }
190
+ ```
191
+
192
+ ```typescript
193
+ this.emitEvent(new TransferredEvent(Blockchain.tx.sender, sender, recipient, amount));
194
+ ```
195
+
196
+ ### TransferredSingleEvent
197
+
198
+ Single token transfer event for ERC1155-style tokens. Event type: `'TransferredSingle'`.
199
+
200
+ ```typescript
201
+ class TransferredSingleEvent extends NetEvent {
202
+ constructor(
203
+ operator: Address, // The address initiating the transfer
204
+ from: Address, // The sender address
205
+ to: Address, // The recipient address
206
+ id: u256, // The token ID
207
+ value: u256 // The amount transferred
208
+ )
209
+ }
210
+ ```
211
+
212
+ ```typescript
213
+ this.emitEvent(new TransferredSingleEvent(Blockchain.tx.sender, from, to, tokenId, amount));
214
+ ```
215
+
216
+ ### TransferredBatchEvent
217
+
218
+ Batch token transfer event for ERC1155-style tokens. Event type: `'TransferredBatch'`. Limited to 3 items due to the 352-byte event size limit.
219
+
220
+ ```typescript
221
+ class TransferredBatchEvent extends NetEvent {
222
+ constructor(
223
+ operator: Address, // The address initiating the transfer
224
+ from: Address, // The sender address
225
+ to: Address, // The recipient address
226
+ ids: u256[], // The token IDs (max 3 items)
227
+ values: u256[] // The amounts transferred (max 3 items)
228
+ )
229
+ }
230
+ ```
231
+
232
+ ```typescript
233
+ this.emitEvent(new TransferredBatchEvent(Blockchain.tx.sender, from, to, tokenIds, amounts));
234
+ ```
235
+
236
+ ### ApprovedEvent
237
+
238
+ Standard approval event. Event type: `'Approved'`.
239
+
240
+ ```typescript
241
+ class ApprovedEvent extends NetEvent {
242
+ constructor(
243
+ owner: Address, // The token owner
244
+ spender: Address, // The approved spender
245
+ amount: u256 // The approved amount
246
+ )
247
+ }
248
+ ```
249
+
250
+ ```typescript
251
+ this.emitEvent(new ApprovedEvent(owner, spender, allowance));
252
+ ```
253
+
254
+ ### ApprovedForAllEvent
255
+
256
+ Operator approval event for all tokens. Event type: `'ApprovedForAll'`.
257
+
258
+ ```typescript
259
+ class ApprovedForAllEvent extends NetEvent {
260
+ constructor(
261
+ account: Address, // The account granting approval
262
+ operator: Address, // The approved operator
263
+ approved: boolean // Whether approval is granted or revoked
264
+ )
265
+ }
266
+ ```
267
+
268
+ ```typescript
269
+ this.emitEvent(new ApprovedForAllEvent(owner, operator, true));
270
+ ```
271
+
272
+ ### MintedEvent
273
+
274
+ Token minting event. Event type: `'Minted'`.
275
+
276
+ ```typescript
277
+ class MintedEvent extends NetEvent {
278
+ constructor(
279
+ to: Address, // The recipient of minted tokens
280
+ amount: u256 // The amount minted
281
+ )
282
+ }
283
+ ```
284
+
285
+ ```typescript
286
+ this.emitEvent(new MintedEvent(recipient, mintAmount));
287
+ ```
288
+
289
+ ### BurnedEvent
290
+
291
+ Token burning event. Event type: `'Burned'`.
292
+
293
+ ```typescript
294
+ class BurnedEvent extends NetEvent {
295
+ constructor(
296
+ from: Address, // The address tokens are burned from
297
+ amount: u256 // The amount burned
298
+ )
299
+ }
300
+ ```
301
+
302
+ ```typescript
303
+ this.emitEvent(new BurnedEvent(burner, burnAmount));
304
+ ```
305
+
306
+ ### URIEvent
307
+
308
+ URI update event for token metadata. Event type: `'URI'`. URI length is limited to 200 bytes.
309
+
310
+ ```typescript
311
+ class URIEvent extends NetEvent {
312
+ constructor(
313
+ value: string, // The URI string (max 200 bytes)
314
+ id: u256 // The token ID
315
+ )
316
+ }
317
+ ```
318
+
319
+ ```typescript
320
+ this.emitEvent(new URIEvent('https://example.com/token/1', tokenId));
321
+ ```
322
+
323
+ ## Event Lifecycle
324
+
325
+ The following sequence diagram shows the complete event lifecycle from creation to storage:
326
+
327
+ ```mermaid
328
+ sequenceDiagram
329
+ participant C as Contract
330
+ participant E as NetEvent
331
+ participant BC as Blockchain
332
+ participant R as Receipt Storage
333
+
334
+ Note over C,R: Event Lifecycle
335
+
336
+ C->>E: new TransferredEvent(operator, from, to, amount)
337
+ E->>E: Create BytesWriter with size
338
+ E->>E: writer.writeAddress(operator)
339
+ E->>E: writer.writeAddress(from)
340
+ E->>E: writer.writeAddress(to)
341
+ E->>E: writer.writeU256(amount)
342
+ E->>E: super('Transferred', data)
343
+
344
+ E->>E: Validate length <= 352 bytes
345
+
346
+ C->>C: this.emitEvent(event)
347
+ C->>BC: Blockchain.emit(event)
348
+
349
+ BC->>E: event.getEventData()
350
+ E->>BC: Return encoded bytes
351
+
352
+ BC->>R: Store in transaction receipt
353
+ R->>R: Format: [4B:typeLen][typeStr][4B:dataLen][data]
354
+
355
+ Note over C,R: Off-chain indexers can now parse events
356
+ ```
357
+
358
+ ## Event Encoding Flow
359
+
360
+ The following diagram shows how events are encoded into binary format:
361
+
362
+ ```mermaid
363
+ flowchart LR
364
+ subgraph "Event Construction"
365
+ A[Event Instance] --> B[Constructor<br/>Parameters]
366
+ B --> C[Create BytesWriter<br/>in constructor]
367
+ end
368
+
369
+ subgraph "BytesWriter Encoding"
370
+ C --> D[BytesWriter]
371
+ D --> E[Write Address<br/>32 bytes]
372
+ D --> F[Write u256<br/>32 bytes]
373
+ D --> G[Write u64<br/>8 bytes]
374
+ D --> H[Write u8<br/>1 byte]
375
+ D --> I[Write bool<br/>1 byte]
376
+ end
377
+
378
+ subgraph "Validation"
379
+ E & F & G & H & I --> J[Combined Buffer]
380
+ J --> K{Size Check}
381
+ K -->|<= 352 bytes| L[Valid Event]
382
+ K -->|> 352 bytes| M[Revert]
383
+ end
384
+
385
+ subgraph "Serialization Format"
386
+ L --> N[4B: type name length]
387
+ N --> O[N bytes: type name UTF-8]
388
+ O --> P[4B: data length]
389
+ P --> Q[M bytes: encoded data]
390
+ end
391
+ ```
392
+
393
+ ## Event Size Limits
394
+
395
+ Events have a maximum payload size of **352 bytes**.
396
+
397
+ | Component | Size |
398
+ |-----------|------|
399
+ | Event type name | Variable |
400
+ | Event data | Up to 352 bytes |
401
+
402
+ ```typescript
403
+ // Calculate event data size
404
+ // Address: 32 bytes, u256: 32 bytes
405
+
406
+ @final
407
+ class LargeEvent extends NetEvent {
408
+ constructor(
409
+ addr1: Address, // 32 bytes
410
+ addr2: Address, // 32 bytes
411
+ value1: u256, // 32 bytes
412
+ value2: u256, // 32 bytes
413
+ value3: u256 // 32 bytes
414
+ ) { // Total: 160 bytes - OK
415
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + U256_BYTE_LENGTH * 3);
416
+ data.writeAddress(addr1);
417
+ data.writeAddress(addr2);
418
+ data.writeU256(value1);
419
+ data.writeU256(value2);
420
+ data.writeU256(value3);
421
+ super('LargeEvent', data);
422
+ }
423
+ }
424
+ ```
425
+
426
+ ## Emitting Events
427
+
428
+ Use `emitEvent` from the contract:
429
+
430
+ ```typescript
431
+ // In contract method
432
+ @method(
433
+ { name: 'to', type: ABIDataTypes.ADDRESS },
434
+ { name: 'amount', type: ABIDataTypes.UINT256 },
435
+ )
436
+ @emit('Transferred')
437
+ public transfer(calldata: Calldata): BytesWriter {
438
+ const to: Address = calldata.readAddress();
439
+ const amount: u256 = calldata.readU256();
440
+ const from: Address = Blockchain.tx.sender;
441
+
442
+ // Perform transfer
443
+ this._transfer(from, to, amount);
444
+
445
+ // Emit event (OP_NET base class handles emitting via internal _transfer)
446
+ // For custom events, use:
447
+ // this.emitEvent(new TransferredEvent(Blockchain.tx.sender, from, to, amount));
448
+
449
+ return new BytesWriter(0);
450
+ }
451
+ ```
452
+
453
+ Or use `Blockchain.emit`:
454
+
455
+ ```typescript
456
+ Blockchain.emit(new TransferredEvent(Blockchain.tx.sender, from, to, amount));
457
+ ```
458
+
459
+ ## Event Encoding Format
460
+
461
+ Events are encoded as:
462
+
463
+ ```
464
+ [4 bytes: type name length]
465
+ [N bytes: type name (UTF-8)]
466
+ [4 bytes: data length]
467
+ [M bytes: event data]
468
+ ```
469
+
470
+ ## Common Event Patterns
471
+
472
+ ### State Change Events
473
+
474
+ ```typescript
475
+ @final
476
+ class OwnershipTransferred extends NetEvent {
477
+ constructor(previousOwner: Address, newOwner: Address) {
478
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH * 2);
479
+ data.writeAddress(previousOwner);
480
+ data.writeAddress(newOwner);
481
+ super('OwnershipTransferred', data);
482
+ }
483
+ }
484
+ ```
485
+
486
+ ### Action Events
487
+
488
+ ```typescript
489
+ @final
490
+ class Paused extends NetEvent {
491
+ constructor(account: Address) {
492
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH);
493
+ data.writeAddress(account);
494
+ super('Paused', data);
495
+ }
496
+ }
497
+
498
+ @final
499
+ class Unpaused extends NetEvent {
500
+ constructor(account: Address) {
501
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH);
502
+ data.writeAddress(account);
503
+ super('Unpaused', data);
504
+ }
505
+ }
506
+ ```
507
+
508
+ ### Indexed-Style Events
509
+
510
+ While OPNet doesn't have Solidity's indexed parameters, you can structure events for efficient filtering:
511
+
512
+ ```typescript
513
+ @final
514
+ class OrderFilled extends NetEvent {
515
+ constructor(
516
+ orderId: u256,
517
+ maker: Address,
518
+ taker: Address,
519
+ amount: u256,
520
+ price: u256
521
+ ) {
522
+ const data = new BytesWriter(U256_BYTE_LENGTH * 3 + ADDRESS_BYTE_LENGTH * 2);
523
+ // Put "indexed" fields first for consistent offset
524
+ data.writeU256(orderId);
525
+ data.writeAddress(maker);
526
+ data.writeAddress(taker);
527
+ data.writeU256(amount);
528
+ data.writeU256(price);
529
+ super('OrderFilled', data);
530
+ }
531
+ }
532
+ ```
533
+
534
+ ## Event Best Practices
535
+
536
+ ### 1. Emit After State Changes
537
+
538
+ ```typescript
539
+ // Good - emit after state is updated
540
+ this._balances.set(to, newBalance);
541
+ this.emitEvent(new TransferredEvent(Blockchain.tx.sender, from, to, amount));
542
+
543
+ // Bad - emit before state change
544
+ this.emitEvent(new TransferredEvent(Blockchain.tx.sender, from, to, amount));
545
+ this._balances.set(to, newBalance); // Could fail
546
+ ```
547
+
548
+ ### 2. Use Descriptive Event Names
549
+
550
+ ```typescript
551
+ // Good - clear event names
552
+ @final class TokensMinted extends NetEvent { ... }
553
+ @final class LiquidityAdded extends NetEvent { ... }
554
+ @final class StakeWithdrawn extends NetEvent { ... }
555
+
556
+ // Less clear
557
+ @final class Action1 extends NetEvent { ... }
558
+ @final class Update extends NetEvent { ... }
559
+ ```
560
+
561
+ ### 3. Include Relevant Context
562
+
563
+ ```typescript
564
+ // Good - includes all relevant data
565
+ @final
566
+ class Swap extends NetEvent {
567
+ constructor(
568
+ user: Address,
569
+ tokenIn: Address,
570
+ tokenOut: Address,
571
+ amountIn: u256,
572
+ amountOut: u256
573
+ ) {
574
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH * 3 + U256_BYTE_LENGTH * 2);
575
+ data.writeAddress(user);
576
+ data.writeAddress(tokenIn);
577
+ data.writeAddress(tokenOut);
578
+ data.writeU256(amountIn);
579
+ data.writeU256(amountOut);
580
+ super('Swap', data);
581
+ }
582
+ }
583
+
584
+ // Less useful - missing context
585
+ @final
586
+ class Swap extends NetEvent {
587
+ constructor(amount: u256) {
588
+ const data = new BytesWriter(U256_BYTE_LENGTH);
589
+ data.writeU256(amount);
590
+ super('Swap', data);
591
+ }
592
+ }
593
+ ```
594
+
595
+ ### 4. Keep Events Consistent
596
+
597
+ ```typescript
598
+ // Use consistent field ordering across similar events
599
+ @final
600
+ class Deposit extends NetEvent {
601
+ constructor(user: Address, token: Address, amount: u256) {
602
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + U256_BYTE_LENGTH);
603
+ data.writeAddress(user);
604
+ data.writeAddress(token);
605
+ data.writeU256(amount);
606
+ super('Deposit', data);
607
+ }
608
+ }
609
+
610
+ @final
611
+ class Withdraw extends NetEvent {
612
+ constructor(user: Address, token: Address, amount: u256) { // Same order
613
+ const data = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + U256_BYTE_LENGTH);
614
+ data.writeAddress(user);
615
+ data.writeAddress(token);
616
+ data.writeU256(amount);
617
+ super('Withdraw', data);
618
+ }
619
+ }
620
+ ```
621
+
622
+ ## Solidity Comparison
623
+
624
+ | Solidity | OPNet |
625
+ |----------|-------|
626
+ | `event Transfer(address indexed from, address indexed to, uint256 value)` | `class TransferredEvent extends NetEvent` |
627
+ | `emit Transfer(from, to, value)` | `emitEvent(new TransferredEvent(operator, from, to, value))` |
628
+ | Indexed parameters | Structure data with important fields first |
629
+ | Anonymous events | Not supported |
630
+
631
+ ## Event Limitations
632
+
633
+ 1. **No indexed parameters** - All parameters are in data payload
634
+ 2. **352-byte limit** - Plan data structure carefully
635
+ 3. **Not accessible on-chain** - Events are for off-chain consumption only
636
+ 4. **No topics** - Single event type string instead of topic hashes
637
+
638
+ ---
639
+
640
+ **Navigation:**
641
+ - Previous: [Storage API](./storage.md)
642
+ - [Back to Documentation Index](../README.md)