opnet 1.8.4 → 1.8.6

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.
@@ -30,7 +30,6 @@ import {
30
30
  | `name()` | - | `string` | Collection name |
31
31
  | `symbol()` | - | `string` | Collection symbol |
32
32
  | `maxSupply()` | - | `bigint` | Maximum supply |
33
- | `collectionInfo()` | - | `{ icon, banner, description, website }` | Collection metadata |
34
33
  | `tokenURI(tokenId)` | `bigint` | `string` | Token metadata URI |
35
34
  | `metadata()` | - | Full metadata object | All metadata in one call |
36
35
 
@@ -79,7 +78,7 @@ import {
79
78
  | `changeMetadata()` | - | - | Trigger metadata change |
80
79
  | `setBaseURI(baseURI)` | `string` | - | Set base URI for tokens |
81
80
  | `domainSeparator()` | - | `Uint8Array` | EIP-712 domain separator |
82
- | `getApproveNonce(owner)` | `Address` | `bigint` | Get nonce for signatures |
81
+ | `nonceOf(owner)` | `Address` | `bigint` | Get nonce for signatures |
83
82
 
84
83
  ---
85
84
 
@@ -94,7 +93,7 @@ interface TransferredEventNFT {
94
93
  operator: Address; // Who initiated the transfer
95
94
  from: Address; // Sender
96
95
  to: Address; // Recipient
97
- amount: bigint; // Amount (1 for single NFT)
96
+ tokenId: bigint; // Token ID
98
97
  }
99
98
  ```
100
99
 
@@ -105,8 +104,8 @@ Emitted when single token approval changes.
105
104
  ```typescript
106
105
  interface ApprovedEventNFT {
107
106
  owner: Address; // Token owner
108
- spender: Address; // Approved spender
109
- amount: bigint; // Token ID as amount
107
+ operator: Address; // Approved operator
108
+ tokenId: bigint; // Token ID
110
109
  }
111
110
  ```
112
111
 
@@ -122,6 +121,28 @@ interface ApprovedForAllEventNFT {
122
121
  }
123
122
  ```
124
123
 
124
+ ### Burned
125
+
126
+ Emitted when a token is burned.
127
+
128
+ ```typescript
129
+ interface BurnedEventNFT {
130
+ from: Address; // Token owner
131
+ tokenId: bigint; // Token ID
132
+ }
133
+ ```
134
+
135
+ ### Minted
136
+
137
+ Emitted when a new token is minted.
138
+
139
+ ```typescript
140
+ interface MintedEventNFT {
141
+ to: Address; // Recipient
142
+ tokenId: bigint; // Token ID
143
+ }
144
+ ```
145
+
125
146
  ### URI
126
147
 
127
148
  Emitted when token URI changes.
@@ -165,10 +186,10 @@ console.log('Collection:', name.properties.name);
165
186
  console.log('Symbol:', symbol.properties.symbol);
166
187
  console.log('Max Supply:', maxSupply.properties.maxSupply);
167
188
 
168
- // Get full collection metadata
169
- const info = await nft.collectionInfo();
170
- console.log('Description:', info.properties.description);
171
- console.log('Website:', info.properties.website);
189
+ // Get full collection metadata in one call
190
+ const metadata = await nft.metadata();
191
+ console.log('Description:', metadata.properties.description);
192
+ console.log('Website:', metadata.properties.website);
172
193
  ```
173
194
 
174
195
  ### Check Ownership
@@ -363,18 +384,6 @@ export const OP_721_ABI: BitcoinInterfaceAbi = [
363
384
  outputs: [{ name: 'maxSupply', type: ABIDataTypes.UINT256 }],
364
385
  type: BitcoinAbiTypes.Function,
365
386
  },
366
- {
367
- name: 'collectionInfo',
368
- constant: true,
369
- inputs: [],
370
- outputs: [
371
- { name: 'icon', type: ABIDataTypes.STRING },
372
- { name: 'banner', type: ABIDataTypes.STRING },
373
- { name: 'description', type: ABIDataTypes.STRING },
374
- { name: 'website', type: ABIDataTypes.STRING },
375
- ],
376
- type: BitcoinAbiTypes.Function,
377
- },
378
387
  {
379
388
  name: 'tokenURI',
380
389
  constant: true,
@@ -549,7 +558,7 @@ export const OP_721_ABI: BitcoinInterfaceAbi = [
549
558
  type: BitcoinAbiTypes.Function,
550
559
  },
551
560
  {
552
- name: 'getApproveNonce',
561
+ name: 'nonceOf',
553
562
  constant: true,
554
563
  inputs: [{ name: 'owner', type: ABIDataTypes.ADDRESS }],
555
564
  outputs: [{ name: 'nonce', type: ABIDataTypes.UINT256 }],
@@ -563,7 +572,7 @@ export const OP_721_ABI: BitcoinInterfaceAbi = [
563
572
  { name: 'operator', type: ABIDataTypes.ADDRESS },
564
573
  { name: 'from', type: ABIDataTypes.ADDRESS },
565
574
  { name: 'to', type: ABIDataTypes.ADDRESS },
566
- { name: 'amount', type: ABIDataTypes.UINT256 },
575
+ { name: 'tokenId', type: ABIDataTypes.UINT256 },
567
576
  ],
568
577
  type: BitcoinAbiTypes.Event,
569
578
  },
@@ -571,8 +580,8 @@ export const OP_721_ABI: BitcoinInterfaceAbi = [
571
580
  name: 'Approved',
572
581
  values: [
573
582
  { name: 'owner', type: ABIDataTypes.ADDRESS },
574
- { name: 'spender', type: ABIDataTypes.ADDRESS },
575
- { name: 'amount', type: ABIDataTypes.UINT256 },
583
+ { name: 'operator', type: ABIDataTypes.ADDRESS },
584
+ { name: 'tokenId', type: ABIDataTypes.UINT256 },
576
585
  ],
577
586
  type: BitcoinAbiTypes.Event,
578
587
  },
@@ -585,6 +594,22 @@ export const OP_721_ABI: BitcoinInterfaceAbi = [
585
594
  ],
586
595
  type: BitcoinAbiTypes.Event,
587
596
  },
597
+ {
598
+ name: 'Burned',
599
+ values: [
600
+ { name: 'from', type: ABIDataTypes.ADDRESS },
601
+ { name: 'tokenId', type: ABIDataTypes.UINT256 },
602
+ ],
603
+ type: BitcoinAbiTypes.Event,
604
+ },
605
+ {
606
+ name: 'Minted',
607
+ values: [
608
+ { name: 'to', type: ABIDataTypes.ADDRESS },
609
+ { name: 'tokenId', type: ABIDataTypes.UINT256 },
610
+ ],
611
+ type: BitcoinAbiTypes.Event,
612
+ },
588
613
  {
589
614
  name: 'URI',
590
615
  values: [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opnet",
3
3
  "type": "module",
4
- "version": "1.8.4",
4
+ "version": "1.8.6",
5
5
  "author": "OP_NET",
6
6
  "description": "The perfect library for building Bitcoin-based applications.",
7
7
  "engines": {
@@ -101,7 +101,7 @@
101
101
  },
102
102
  "devDependencies": {
103
103
  "@babel/core": "^7.29.0",
104
- "@babel/preset-env": "^7.29.0",
104
+ "@babel/preset-env": "^7.29.2",
105
105
  "@babel/preset-typescript": "^7.28.5",
106
106
  "@eslint/js": "^10.0.1",
107
107
  "@microsoft/api-extractor": "7.57.7",
@@ -116,7 +116,7 @@
116
116
  "stream-browserify": "^3.0.0",
117
117
  "typedoc": "^0.28.17",
118
118
  "typescript": "^5.9.3",
119
- "typescript-eslint": "^8.57.0",
119
+ "typescript-eslint": "^8.57.1",
120
120
  "vite": "^8.0.0",
121
121
  "vite-plugin-dts": "4.5.4",
122
122
  "vite-plugin-node-polyfills": "^0.25.0",
@@ -143,7 +143,7 @@
143
143
  "p-limit": "^7.3.0",
144
144
  "pako": "^2.1.0",
145
145
  "protobufjs": "^8.0.0",
146
- "undici": "^7.24.0"
146
+ "undici": "^7.24.4"
147
147
  },
148
148
  "overrides": {
149
149
  "vite-plugin-node-polyfills": {
package/src/_version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '1.8.4';
1
+ export const version = '1.8.5';
@@ -23,7 +23,7 @@ export const OP721Events: BitcoinInterfaceAbi = [
23
23
  type: ABIDataTypes.ADDRESS,
24
24
  },
25
25
  {
26
- name: 'amount',
26
+ name: 'tokenId',
27
27
  type: ABIDataTypes.UINT256,
28
28
  },
29
29
  ],
@@ -37,11 +37,11 @@ export const OP721Events: BitcoinInterfaceAbi = [
37
37
  type: ABIDataTypes.ADDRESS,
38
38
  },
39
39
  {
40
- name: 'spender',
40
+ name: 'operator',
41
41
  type: ABIDataTypes.ADDRESS,
42
42
  },
43
43
  {
44
- name: 'amount',
44
+ name: 'tokenId',
45
45
  type: ABIDataTypes.UINT256,
46
46
  },
47
47
  ],
@@ -65,6 +65,34 @@ export const OP721Events: BitcoinInterfaceAbi = [
65
65
  ],
66
66
  type: BitcoinAbiTypes.Event,
67
67
  },
68
+ {
69
+ name: 'Burned',
70
+ values: [
71
+ {
72
+ name: 'from',
73
+ type: ABIDataTypes.ADDRESS
74
+ },
75
+ {
76
+ name: 'tokenId',
77
+ type: ABIDataTypes.UINT256
78
+ },
79
+ ],
80
+ type: BitcoinAbiTypes.Event,
81
+ },
82
+ {
83
+ name: 'Minted',
84
+ values: [
85
+ {
86
+ name: 'to',
87
+ type: ABIDataTypes.ADDRESS,
88
+ },
89
+ {
90
+ name: 'tokenId',
91
+ type: ABIDataTypes.UINT256,
92
+ },
93
+ ],
94
+ type: BitcoinAbiTypes.Event,
95
+ },
68
96
  {
69
97
  name: 'URI',
70
98
  values: [
@@ -121,30 +149,6 @@ export const OP_721_ABI: BitcoinInterfaceAbi = [
121
149
  },
122
150
  ],
123
151
  },
124
- {
125
- name: 'collectionInfo',
126
- type: BitcoinAbiTypes.Function,
127
- constant: true,
128
- inputs: [],
129
- outputs: [
130
- {
131
- name: 'icon',
132
- type: ABIDataTypes.STRING,
133
- },
134
- {
135
- name: 'banner',
136
- type: ABIDataTypes.STRING,
137
- },
138
- {
139
- name: 'description',
140
- type: ABIDataTypes.STRING,
141
- },
142
- {
143
- name: 'website',
144
- type: ABIDataTypes.STRING,
145
- },
146
- ],
147
- },
148
152
  {
149
153
  name: 'tokenURI',
150
154
  type: BitcoinAbiTypes.Function,
@@ -426,7 +430,7 @@ export const OP_721_ABI: BitcoinInterfaceAbi = [
426
430
  ],
427
431
  },
428
432
  {
429
- name: 'getApproveNonce',
433
+ name: 'nonceOf',
430
434
  type: BitcoinAbiTypes.Function,
431
435
  constant: true,
432
436
  inputs: [
@@ -8,7 +8,6 @@ import {
8
8
  } from './interfaces/IBlockWitness.js';
9
9
 
10
10
  export class BlockWitnessAPI implements IBlockWitnessAPI {
11
- public readonly trusted: boolean;
12
11
  public readonly signature: Uint8Array;
13
12
  public readonly timestamp: number;
14
13
  public readonly proofs: readonly Uint8Array[];
@@ -16,7 +15,6 @@ export class BlockWitnessAPI implements IBlockWitnessAPI {
16
15
  public readonly publicKey?: Address;
17
16
 
18
17
  constructor(data: RawBlockWitnessAPI) {
19
- this.trusted = data.trusted;
20
18
  this.signature = stringBase64ToBuffer(data.signature);
21
19
  this.timestamp = data.timestamp;
22
20
  this.proofs = Object.freeze(data.proofs.map((proof) => stringBase64ToBuffer(proof)));
@@ -1,7 +1,6 @@
1
1
  import { Address } from '@btc-vision/transaction';
2
2
 
3
3
  export interface IBlockWitnessAPI {
4
- readonly trusted: boolean;
5
4
  readonly signature: Uint8Array;
6
5
  readonly timestamp: number;
7
6
 
@@ -12,7 +11,6 @@ export interface IBlockWitnessAPI {
12
11
  }
13
12
 
14
13
  export interface RawBlockWitnessAPI {
15
- readonly trusted: boolean;
16
14
  readonly signature: string;
17
15
  readonly timestamp: number;
18
16
 
@@ -1,13 +1,5 @@
1
1
  import { QuantumBIP32Interface } from '@btc-vision/bip32';
2
- import {
3
- fromBase64,
4
- fromHex,
5
- Network,
6
- networks,
7
- PsbtOutputExtended,
8
- Signer,
9
- toHex,
10
- } from '@btc-vision/bitcoin';
2
+ import { fromBase64, fromHex, Network, networks, PsbtOutputExtended, Signer, toHex, } from '@btc-vision/bitcoin';
11
3
  import { UniversalSigner } from '@btc-vision/ecpair';
12
4
  import {
13
5
  Address,
@@ -816,6 +808,34 @@ export class CallResult<
816
808
  return a > b ? a : b;
817
809
  }
818
810
 
811
+ private ensureUTXOsAvailable(
812
+ utxos: UTXO[] | undefined | null,
813
+ ): asserts utxos is UTXO[] & { length: number } {
814
+ if (!utxos || utxos.length === 0) {
815
+ throw new Error(
816
+ 'Wallet optimization required. No UTXOs available. You may need to split your wallet UTXOs so at ' +
817
+ 'least one non-extra-input UTXO is available for the funding transaction.',
818
+ );
819
+ }
820
+ }
821
+
822
+ private computeRequiredAmount(
823
+ gasFee: bigint,
824
+ priority: bigint,
825
+ amountAddition: bigint,
826
+ totalOuts: bigint,
827
+ extraInputValue: bigint,
828
+ miningCost: bigint = 0n,
829
+ maximumAllowedSatToSpend: bigint = 0n,
830
+ ): bigint {
831
+ const gross = this.max(
832
+ gasFee + priority + amountAddition + totalOuts + miningCost,
833
+ maximumAllowedSatToSpend,
834
+ );
835
+
836
+ return gross > extraInputValue ? gross - extraInputValue : 1n;
837
+ }
838
+
819
839
  /**
820
840
  * Acquire UTXOs for the transaction.
821
841
  * @param {TransactionParameters} interactionParams - The transaction parameters.
@@ -841,13 +861,25 @@ export class CallResult<
841
861
 
842
862
  const gasFee = this.bigintMax(this.estimatedSatGas, interactionParams.minGas ?? 0n);
843
863
 
844
- const preWant = this.max(
845
- gasFee + priority + amountAddition + totalOuts,
864
+ const extraInputValue = (interactionParams.extraInputs ?? []).reduce(
865
+ (s, u) => s + u.value,
866
+ 0n,
867
+ );
868
+
869
+ const preWant = this.computeRequiredAmount(
870
+ gasFee,
871
+ priority,
872
+ amountAddition,
873
+ totalOuts,
874
+ extraInputValue,
875
+ 0n,
846
876
  interactionParams.maximumAllowedSatToSpend,
847
877
  );
848
878
 
849
879
  let utxos = interactionParams.utxos ?? (await this.#fetchUTXOs(preWant, interactionParams));
850
880
 
881
+ this.ensureUTXOsAvailable(utxos);
882
+
851
883
  let refetched = false;
852
884
  while (true) {
853
885
  const miningCost = TransactionHelper.estimateMiningCost(
@@ -858,8 +890,13 @@ export class CallResult<
858
890
  feeRate,
859
891
  );
860
892
 
861
- const want = this.max(
862
- gasFee + priority + amountAddition + totalOuts + miningCost,
893
+ const want = this.computeRequiredAmount(
894
+ gasFee,
895
+ priority,
896
+ amountAddition,
897
+ totalOuts,
898
+ extraInputValue,
899
+ miningCost,
863
900
  interactionParams.maximumAllowedSatToSpend,
864
901
  );
865
902
 
@@ -873,6 +910,8 @@ export class CallResult<
873
910
  utxos = await this.#fetchUTXOs(want, interactionParams);
874
911
  refetched = true;
875
912
 
913
+ this.ensureUTXOsAvailable(utxos);
914
+
876
915
  const haveAfter = utxos.reduce((s, u) => s + u.value, 0n);
877
916
  if (haveAfter === have) {
878
917
  throw new Error('Not enough sat to complete transaction');
@@ -759,7 +759,6 @@ export abstract class AbstractRpcProvider {
759
759
  * Get block witnesses.
760
760
  * @description This method is used to get the witnesses of a block. This proves that the actions executed inside a block are valid and confirmed by the network. If the minimum number of witnesses are not met, the block is considered as potentially invalid.
761
761
  * @param {BlockTag} height The block number or hash, use -1 for latest block
762
- * @param {boolean} [trusted] Whether to trust the witnesses or not
763
762
  * @param {number} [limit] The maximum number of witnesses to return
764
763
  * @param {number} [page] The page number of the witnesses
765
764
  * @returns {Promise<BlockWitnesses>} The witnesses of the block
@@ -768,13 +767,11 @@ export abstract class AbstractRpcProvider {
768
767
  */
769
768
  public async getBlockWitness(
770
769
  height: BigNumberish = -1,
771
- trusted?: boolean,
772
770
  limit?: number,
773
771
  page?: number,
774
772
  ): Promise<BlockWitnesses> {
775
- const params: [BigNumberish, boolean?, number?, number?] = [height.toString()];
773
+ const params: [BigNumberish, number?, number?] = [height.toString()];
776
774
 
777
- if (trusted !== undefined && trusted !== null) params.push(trusted);
778
775
  if (limit !== undefined && limit !== null) params.push(limit);
779
776
  if (page !== undefined && page !== null) params.push(page);
780
777
 
@@ -398,12 +398,11 @@ export class WebSocketRpcProvider extends AbstractRpcProvider {
398
398
  };
399
399
 
400
400
  case JSONRpcMethods.BLOCK_WITNESS:
401
- // GetBlockWitnessRequest: requestId=1, height=2, trusted=3, limit=4, page=5
401
+ // GetBlockWitnessRequest: requestId=1, height=2, limit=3, page=4
402
402
  return {
403
403
  2: Long.fromString(String(params[0] ?? -1)),
404
404
  3: params[1],
405
405
  4: params[2],
406
- 5: params[3],
407
406
  };
408
407
 
409
408
  case JSONRpcMethods.GAS:
@@ -5,7 +5,7 @@ import { AddressTypes } from '@btc-vision/transaction';
5
5
  import type { JsonRpcPayload } from '../src/providers/interfaces/JSONRpc.js';
6
6
  import type { JsonRpcCallResult } from '../src/providers/interfaces/JSONRpcResult.js';
7
7
  import type { MempoolInfo } from '../src/providers/interfaces/mempool/MempoolInfo.js';
8
- import type { IMempoolTransactionData } from '../src/providers/interfaces/mempool/MempoolTransactionData.js';
8
+ import type { IMempoolTransactionData, IMempoolOPNetTransactionData } from '../src/providers/interfaces/mempool/MempoolTransactionData.js';
9
9
 
10
10
  // ============================================================================
11
11
  // Mock provider that intercepts _send
@@ -146,7 +146,7 @@ describe('Mempool API - Unit Tests', () => {
146
146
  // ========================================================================
147
147
 
148
148
  describe('getPendingTransaction', () => {
149
- const mockTx: IMempoolTransactionData = {
149
+ const mockTx: IMempoolOPNetTransactionData = {
150
150
  id: 'abc123def456abc123def456abc123def456abc123def456abc123def456abc1',
151
151
  firstSeen: '2023-11-14T22:13:20.000Z',
152
152
  blockHeight: '0xcf080',
@@ -270,13 +270,14 @@ describe('Mempool API - Unit Tests', () => {
270
270
 
271
271
  it('should handle Generic transaction', async () => {
272
272
  const nonOPNetTx: IMempoolTransactionData = {
273
- ...mockTx,
273
+ id: mockTx.id,
274
+ firstSeen: mockTx.firstSeen,
275
+ blockHeight: mockTx.blockHeight,
274
276
  transactionType: 'Generic',
275
- theoreticalGasLimit: undefined,
276
- priorityFee: undefined,
277
- from: undefined,
278
- contractAddress: undefined,
279
- calldata: undefined,
277
+ psbt: mockTx.psbt,
278
+ inputs: mockTx.inputs,
279
+ outputs: mockTx.outputs,
280
+ raw: mockTx.raw,
280
281
  };
281
282
 
282
283
  provider.mockSend.mockResolvedValue([
@@ -350,7 +351,7 @@ describe('Mempool API - Unit Tests', () => {
350
351
  // ========================================================================
351
352
 
352
353
  describe('getLatestPendingTransactions', () => {
353
- const mockTx1: IMempoolTransactionData = {
354
+ const mockTx1: IMempoolOPNetTransactionData = {
354
355
  id: 'a000000000000000000000000000000000000000000000000000000000000001',
355
356
  firstSeen: '2023-11-14T22:13:20.000Z',
356
357
  blockHeight: '0xcf080',
@@ -603,7 +604,7 @@ describe('Mempool API - Unit Tests', () => {
603
604
  // ========================================================================
604
605
 
605
606
  describe('getLatestPendingTransactionsByAddresses', () => {
606
- const mockTx1: IMempoolTransactionData = {
607
+ const mockTx1: IMempoolOPNetTransactionData = {
607
608
  id: 'a000000000000000000000000000000000000000000000000000000000000001',
608
609
  firstSeen: '2023-11-14T22:13:20.000Z',
609
610
  blockHeight: '0xcf080',
@@ -710,12 +711,12 @@ describe('Mempool API - Unit Tests', () => {
710
711
  // Integration Tests - Real Regtest Network
711
712
  // ============================================================================
712
713
 
713
- describe('Mempool API - Integration Tests (regtest.opnet.org)', () => {
714
- const REGTEST_URL = 'https://regtest.opnet.org';
714
+ describe('Mempool API - Integration Tests (testnet.opnet.org)', () => {
715
+ const TESTNET_URL = 'https://testnet.opnet.org';
715
716
  let provider: JSONRpcProvider;
716
717
 
717
718
  beforeEach(() => {
718
- provider = new JSONRpcProvider({ url: REGTEST_URL, network: networks.regtest });
719
+ provider = new JSONRpcProvider({ url: TESTNET_URL, network: networks.opnetTestnet });
719
720
  });
720
721
 
721
722
  describe('getMempoolInfo', () => {
@@ -745,8 +746,8 @@ describe('Mempool API - Integration Tests (regtest.opnet.org)', () => {
745
746
  if (txs.length > 0) {
746
747
  const tx = txs[0];
747
748
  expect(typeof tx.id).toBe('string');
748
- expect(typeof tx.firstSeen).toBe('string');
749
- expect(typeof tx.blockHeight).toBe('string');
749
+ expect(tx.firstSeen).toBeDefined();
750
+ expect(tx.blockHeight).toBeDefined();
750
751
  expect(typeof tx.transactionType).toBe('string');
751
752
  expect(typeof tx.psbt).toBe('boolean');
752
753
  expect(Array.isArray(tx.inputs)).toBe(true);