@tchain/tcabci-read-js-client 2.7.12 → 2.8.0

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.
package/message.js CHANGED
@@ -1,17 +1,20 @@
1
+ import { SendThrow } from './util.js'
1
2
  import { INVALID_ARGUMENT_WITH_CS } from './errors.js'
2
3
  import { TX_TYPE_LIST } from './transaction.js'
3
- import { Debug } from '@streetbyters/js-debug'
4
+ import {
5
+ addresses,
6
+ signedData as validateSignedData,
7
+ cloneAndFreeze
8
+ } from './validation.js'
4
9
 
5
10
  export const SUBSCRIBEMessage = 'subscribe',
6
- UNSUBSCRIBEMessage = 'unsubscribe'
7
-
8
- export const Block = 0,
11
+ UNSUBSCRIBEMessage = 'unsubscribe',
12
+ Block = 0,
9
13
  Transaction = 1,
10
14
  Subscription = 2,
11
15
  Listen = 3,
12
- MSG = 4
13
-
14
- export const OK = 1,
16
+ MSG = 4,
17
+ OK = 1,
15
18
  FAIL = 2
16
19
 
17
20
  export default class Message {
@@ -41,10 +44,16 @@ export default class Message {
41
44
  } = {}) {
42
45
  this._is_web = isWeb
43
46
  this._type = type
44
- if (addrs && Array.isArray(addrs)) this._addresses = addrs
45
- if (typeof signedData === 'object') this._signedAddresses = signedData
46
- if (txTypes && Array.isArray(txTypes)) this._txTypes = txTypes
47
- if (data) this._data = data
47
+
48
+ if (addrs && Array.isArray(addrs))
49
+ this._addresses = Object.freeze(addresses(addrs))
50
+
51
+ if (signedData !== null) this._signedAddresses = cloneAndFreeze(signedData)
52
+
53
+ if (txTypes && Array.isArray(txTypes))
54
+ this._txTypes = Object.freeze([...txTypes])
55
+
56
+ if (data !== null) this._data = cloneAndFreeze(data)
48
57
  }
49
58
 
50
59
  get IsWeb() {
@@ -55,14 +64,22 @@ export default class Message {
55
64
  return this._type
56
65
  }
57
66
 
67
+ /** @returns {ReadonlyArray<string>|undefined} Frozen snapshot when present. */
58
68
  get Addresses() {
59
69
  return this._addresses
60
70
  }
61
71
 
72
+ /** @returns {Readonly<Record<string, string>>|undefined} Frozen snapshot when present. */
62
73
  get SignedAddresses() {
63
74
  return this._signedAddresses
64
75
  }
65
76
 
77
+ /** @returns {ReadonlyArray<import('./transaction.js').TXType>|undefined} Frozen snapshot when present. */
78
+ get TXTypes() {
79
+ return this._txTypes
80
+ }
81
+
82
+ /** @returns {import('./types.js').JSONValue|undefined} Frozen snapshot when present. */
66
83
  get Data() {
67
84
  return this._data
68
85
  }
@@ -71,47 +88,50 @@ export default class Message {
71
88
  return this._state
72
89
  }
73
90
 
91
+ /** @param {string} value @returns {import('./types.js').ParseResult<'message', Readonly<Message>>} */
74
92
  static FromJSON(value) {
75
- try {
76
- const msg = new Message(),
77
- parsed = JSON.parse(value)
78
-
79
- msg._type = parsed.type
80
- if (typeof parsed.addresses !== 'undefined')
81
- msg._addresses = parsed.addresses
82
- if (typeof parsed.signed_addresses !== 'undefined')
83
- msg._signedAddresses = parsed.signed_addresses
84
- if (typeof parsed.data !== 'undefined') msg._data = parsed.data
85
- if (typeof parsed.tx_types !== 'undefined') msg._txTypes = parsed.tx_types
86
- if (typeof parsed.state !== 'undefined') msg._state = parsed.state
87
-
88
- msg._validate()
93
+ if (typeof value !== 'string')
94
+ return { message: null, error: new Error('Invalid message JSON') }
89
95
 
90
- return { message: this, error: null }
91
- } catch (e) {
92
- Debug.error(e)
93
- return { message: null, error: e }
96
+ try {
97
+ return Message.FromObject(JSON.parse(value))
98
+ } catch {
99
+ return { message: null, error: new Error('Invalid message JSON') }
94
100
  }
95
101
  }
96
102
 
103
+ /** @param {Record<string, unknown>} obj @returns {import('./types.js').ParseResult<'message', Readonly<Message>>} */
97
104
  static FromObject(obj) {
98
105
  try {
106
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj))
107
+ SendThrow(new TypeError('Invalid message'))
108
+
99
109
  const msg = new Message()
100
110
 
101
111
  msg._type = obj.type
102
- if (typeof obj.addresses !== 'undefined') msg._addresses = obj.addresses
112
+
113
+ if (typeof obj.is_web !== 'undefined') msg._is_web = obj.is_web
114
+
115
+ if (typeof obj.addresses !== 'undefined')
116
+ msg._addresses = Object.freeze(addresses(obj.addresses))
117
+
103
118
  if (typeof obj.signed_addresses !== 'undefined')
104
- msg._signedAddresses = obj.signed_addresses
105
- if (typeof obj.data !== 'undefined') msg._data = obj.data
106
- if (typeof obj.tx_types !== 'undefined') msg._txTypes = obj.tx_types
119
+ msg._signedAddresses = Object.freeze(
120
+ validateSignedData(obj.signed_addresses)
121
+ )
122
+
123
+ if (typeof obj.data !== 'undefined') msg._data = cloneAndFreeze(obj.data)
124
+
125
+ if (typeof obj.tx_types !== 'undefined')
126
+ msg._txTypes = cloneAndFreeze(obj.tx_types)
127
+
107
128
  if (typeof obj.state !== 'undefined') msg._state = obj.state
108
129
 
109
130
  msg._validate()
110
131
 
111
- return { message: this, error: null }
112
- } catch (e) {
113
- Debug.error(e)
114
- return { message: null, error: e }
132
+ return { message: Object.freeze(msg), error: null }
133
+ } catch {
134
+ return { message: null, error: new Error('Invalid message payload') }
115
135
  }
116
136
  }
117
137
 
@@ -126,7 +146,8 @@ export default class Message {
126
146
  ? { signed_addresses: this._signedAddresses }
127
147
  : {}),
128
148
  ...(this._txTypes ? { tx_types: this._txTypes } : {}),
129
- ...(this._data ? { data: this._data } : {})
149
+ ...(typeof this._data !== 'undefined' ? { data: this._data } : {}),
150
+ ...(typeof this._state !== 'undefined' ? { state: this._state } : {})
130
151
  })
131
152
  }
132
153
 
@@ -138,21 +159,18 @@ export default class Message {
138
159
  throw new Error(INVALID_ARGUMENT_WITH_CS('is_web'))
139
160
  }
140
161
 
141
- if (typeof this._type === 'undefined') {
162
+ if (
163
+ ![
164
+ SUBSCRIBEMessage,
165
+ UNSUBSCRIBEMessage,
166
+ Block,
167
+ Transaction,
168
+ Subscription,
169
+ Listen,
170
+ MSG
171
+ ].includes(this._type)
172
+ )
142
173
  throw new Error(INVALID_ARGUMENT_WITH_CS('type'))
143
- } else {
144
- if (
145
- typeof this._type === 'string' &&
146
- ![SUBSCRIBEMessage, UNSUBSCRIBEMessage].includes(this._type)
147
- ) {
148
- throw new Error(INVALID_ARGUMENT_WITH_CS('type'))
149
- } else if (
150
- typeof this._type === 'number' &&
151
- ![Block, Transaction, Subscription, Listen, MSG].includes(this._type)
152
- ) {
153
- throw new Error(INVALID_ARGUMENT_WITH_CS('type'))
154
- }
155
- }
156
174
 
157
175
  if (
158
176
  typeof this._addresses !== 'undefined' &&
@@ -168,7 +186,13 @@ export default class Message {
168
186
  throw new Error(INVALID_ARGUMENT_WITH_CS('signedAddresses'))
169
187
  }
170
188
 
171
- if (typeof this._txTypes !== 'undefined' && this._txTypes.length) {
189
+ if (typeof this._txTypes !== 'undefined') {
190
+ if (
191
+ !Array.isArray(this._txTypes) ||
192
+ this._txTypes.length > TX_TYPE_LIST.length
193
+ )
194
+ throw new Error(INVALID_ARGUMENT_WITH_CS('tx_types'))
195
+
172
196
  for (let i = 0; i < this._txTypes.length; i++) {
173
197
  if (!TX_TYPE_LIST.includes(this._txTypes[i])) {
174
198
  throw new Error(INVALID_ARGUMENT_WITH_CS('tx_types'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tchain/tcabci-read-js-client",
3
- "version": "2.7.12",
3
+ "version": "2.8.0",
4
4
  "description": "TransferChain Fastest Read Network WebSocket Client",
5
5
  "homepage": "https://github.com/TransferChain/tcabci-read-js-client#readme",
6
6
  "bugs": {
@@ -24,35 +24,40 @@
24
24
  "transaction.js",
25
25
  "util.js",
26
26
  "websocket.js",
27
- "websocketOptions.js"
27
+ "websocketOptions.js",
28
+ "bytea.js",
29
+ "validation.js"
28
30
  ],
29
31
  "type": "module",
30
32
  "main": "client.js",
31
- "scripts": {
32
- "format": "oxfmt ./",
33
- "lint": "oxfmt ./ && oxlint --fix ./",
34
- "lint:check": "oxfmt --check ./ && oxlint ./",
35
- "test": "export NODE_ENV=test || SET \"NODE_ENV=test\" && mocha --require esm --timeout 5000",
36
- "test:all": "export NODE_ENV=test || SET \"NODE_ENV=test\" && mocha --require esm --timeout 5000 '*_test.js'",
37
- "test:coverage": "export NODE_ENV=test || SET \"NODE_ENV=test\" && nyc --reporter=text mocha --require esm --timeout 5000"
38
- },
33
+ "types": "client.d.ts",
39
34
  "dependencies": {
40
- "@streetbyters/js-debug": "^0.1.3",
41
35
  "cockatiel": "^4.0.0",
42
36
  "reconnecting-websocket": "^4.4.0"
43
37
  },
44
38
  "devDependencies": {
45
39
  "@types/chai": "^5.2.3",
46
40
  "chai": "^6.2.2",
47
- "esm": "^3.2.25",
48
- "express": "^5.2.1",
49
- "globals": "^16.5.0",
50
41
  "mocha": "^11.8.0",
51
- "nyc": "^18.0.0",
52
42
  "oxfmt": "^0.63.0",
53
43
  "oxlint": "^1.84.0",
44
+ "typescript": "^5.9.3",
54
45
  "unit.js": "^2.1.1",
55
46
  "ws": "^8.21.3"
56
47
  },
57
- "packageManager": "pnpm@12.5.1"
58
- }
48
+ "engines": {
49
+ "node": ">=24.0.0"
50
+ },
51
+ "scripts": {
52
+ "format": "oxfmt ./",
53
+ "lint": "oxfmt ./ && oxlint --fix ./",
54
+ "lint:check": "oxfmt --check ./ && oxlint ./",
55
+ "test": "pnpm run test:unit && pnpm run test:security && pnpm run test:types",
56
+ "test:all": "pnpm test",
57
+ "test:coverage": "node --experimental-test-coverage --test test/security.test.js",
58
+ "test:unit": "mocha --timeout 5000 test/errors_test.js test/websocketOptions_test.js test/websocket_test.js",
59
+ "test:security": "node --test test/security.test.js",
60
+ "test:types": "tsc --noEmit --strict --module NodeNext --moduleResolution NodeNext --target ES2022 test/consumer.ts",
61
+ "test:integration": "mocha --timeout 7000 test/client_test.js"
62
+ }
63
+ }
package/transaction.d.ts CHANGED
@@ -1,104 +1,190 @@
1
- export declare type TXType = string
2
-
3
- export declare const TX_TYPE_MASTER: TXType,
4
- TX_TYPE_ADDRESS: TXType,
5
- TX_TYPE_ADDRESSES: TXType,
6
- TX_TYPE_ACCOUNT: TXType,
7
- TX_TYPE_ACCOUNT_INITIAL_TXS: TXType,
8
- TX_TYPE_MESSAGE: TXType,
9
- TX_TYPE_MESSAGE_SENT: TXType,
10
- TX_TYPE_MESSAGE_THREAD_DELETE: TXType,
11
- TX_TYPE_TRANSFER: TXType,
12
- TX_TYPE_TRANSFER_CANCEL: TXType,
13
- TX_TYPE_TRANSFER_SENT: TXType,
14
- TX_TYPE_TRANSFER_RECEIVE_DELETE: TXType,
15
- TX_TYPE_TRANSFER_INFO: TXType,
16
- TX_TYPE_STORAGE: TXType,
17
- TX_TYPE_STORAGE_DELETE: TXType,
18
- TX_TYPE_BACKUP: TXType,
19
- TX_TYPE_CONTACT: TXType,
20
- TX_TYPE_FILE_VIRTUAL: TXType,
21
- TX_TYPE_FILE_FS: TXType,
22
- TX_TYPE_RFILE_VIRTUAL: TXType,
23
- TX_TYPE_RFILE_FS: TXType,
24
- TX_TYPE_DFILE_VIRTUAL: TXType,
25
- TX_TYPE_DFILE_FS: TXType,
26
- TX_TYPE_PFILE_VIRTUAL: TXType,
27
- TX_TYPE_REQUEST: TXType,
28
- TX_TYPE_REQUEST_IN: TXType,
29
- TX_TYPE_REQUEST_UPLOAD: TXType,
30
- TX_TYPE_REQUEST_CANCEL: TXType,
31
- TX_TYPE_DATA_ROOM: TXType,
32
- TX_TYPE_DATA_ROOMF: TXType,
33
- TX_TYPE_DATA_ROOM_POLICY: TXType,
34
- TX_TYPE_DATA_ROOM_DATA: TXType,
35
- TX_TYPE_DATA_ROOM_DATA_DELETE: TXType,
36
- TX_TYPE_DATA_ROOM_DATA_POLICY: TXType,
37
- TX_TYPE_DATA_ROOME: TXType,
38
- TX_TYPE_DATA_ROOME_DATA: TXType,
39
- TX_TYPE_MULTI_DATA_ROOM: TXType,
40
- TX_TYPE_MULTI_STORAGE: TXType,
41
- TX_TYPE_MULTI_TRANSFER: TXType,
42
- TX_TYPE_MULTI_TRANSFER_SENT: TXType,
43
- TX_TYPE_MULTI_BACKUP: TXType,
44
- TX_TYPE_MULTI_PASSWD: TXType,
45
- TX_TYPE_MULTI_COLLECTION: TXType,
46
- TX_TYPE_MULTI_DATAV2: TXType,
47
- TX_TYPE_PASSWD_DATA: TXType,
48
- TX_TYPE_PASSWD_ROOM: TXType,
49
- TX_TYPE_PASSWD_ROOMF: TXType,
50
- TX_TYPE_PASSWD_ROOM_POLICY: TXType,
51
- TX_TYPE_PASSWD_ROOM_DATA: TXType,
52
- TX_TYPE_PASSWD_ROOM_DATA_DELETE: TXType,
53
- TX_TYPE_PASSWD_ROOM_DATA_POLICY: TXType,
54
- TX_TYPE_DATAV2: TXType,
55
- TX_TYPE_DATAV2_POLICY: TXType,
56
- TX_TYPE_COLLECTION: TXType,
57
- TX_TYPE_COLLECTION_POLICY: TXType,
58
- TX_TYPE_DATAV2_COLLECTION: TXType,
59
- TX_TYPE_DATAV2F: TXType
60
-
61
- export declare const TX_TYPE_LIST: TXType[]
1
+ import { JSONValue, ParseResult } from './types.js'
62
2
 
3
+ export type TXType =
4
+ | 'initial_storage'
5
+ | 'interim_storage'
6
+ | 'interim_storages'
7
+ | 'initial_account'
8
+ | 'initial_account_txs'
9
+ | 'message'
10
+ | 'inherit_message'
11
+ | 'inherit_message_recv'
12
+ | 'transfer'
13
+ | 'transfer_Cancel'
14
+ | 'transfer_sent'
15
+ | 'transfer_receive_delete'
16
+ | 'transfer_info'
17
+ | 'storage'
18
+ | 'storage_delete'
19
+ | 'backup'
20
+ | 'interim_message'
21
+ | 'fs_virt'
22
+ | 'fs_real'
23
+ | 'fs_rvirt'
24
+ | 'fs_rreal'
25
+ | 'fs_dvirt'
26
+ | 'fs_dreal'
27
+ | 'fs_pvirt'
28
+ | 'request'
29
+ | 'request_in'
30
+ | 'request_upload'
31
+ | 'request_Cancel'
32
+ | 'data_room'
33
+ | 'data_roomF'
34
+ | 'data_room_policy'
35
+ | 'data_room_data'
36
+ | 'data_room_data_delete'
37
+ | 'data_room_data_policy'
38
+ | 'data_roomE'
39
+ | 'data_roomE_data'
40
+ | 'multi_data_room'
41
+ | 'multi_storage'
42
+ | 'multi_transfer'
43
+ | 'multi_transfer_sent'
44
+ | 'multi_backup'
45
+ | 'multi_passwd'
46
+ | 'multi_collection'
47
+ | 'multi_dataV2'
48
+ | 'passwd_data'
49
+ | 'passwd_room'
50
+ | 'passwd_roomF'
51
+ | 'passwd_room_policy'
52
+ | 'passwd_room_data'
53
+ | 'passwd_room_data_delete'
54
+ | 'passwd_room_data_policy'
55
+ | 'datav2'
56
+ | 'datav2_policy'
57
+ | 'coll'
58
+ | 'coll_policy'
59
+ | 'datav2_coll'
60
+ | 'datav2F'
61
+
62
+ export declare const TX_TYPE_MASTER: 'initial_storage',
63
+ TX_TYPE_ADDRESS: 'interim_storage',
64
+ TX_TYPE_ADDRESSES: 'interim_storages',
65
+ TX_TYPE_ACCOUNT: 'initial_account',
66
+ TX_TYPE_ACCOUNT_INITIAL_TXS: 'initial_account_txs',
67
+ TX_TYPE_MESSAGE: 'message',
68
+ TX_TYPE_MESSAGE_SENT: 'inherit_message',
69
+ TX_TYPE_MESSAGE_THREAD_DELETE: 'inherit_message_recv',
70
+ TX_TYPE_TRANSFER: 'transfer',
71
+ TX_TYPE_TRANSFER_CANCEL: 'transfer_Cancel',
72
+ TX_TYPE_TRANSFER_SENT: 'transfer_sent',
73
+ TX_TYPE_TRANSFER_RECEIVE_DELETE: 'transfer_receive_delete',
74
+ TX_TYPE_TRANSFER_INFO: 'transfer_info',
75
+ TX_TYPE_STORAGE: 'storage',
76
+ TX_TYPE_STORAGE_DELETE: 'storage_delete',
77
+ TX_TYPE_BACKUP: 'backup',
78
+ TX_TYPE_CONTACT: 'interim_message',
79
+ TX_TYPE_FILE_VIRTUAL: 'fs_virt',
80
+ TX_TYPE_FILE_FS: 'fs_real',
81
+ TX_TYPE_RFILE_VIRTUAL: 'fs_rvirt',
82
+ TX_TYPE_RFILE_FS: 'fs_rreal',
83
+ TX_TYPE_DFILE_VIRTUAL: 'fs_dvirt',
84
+ TX_TYPE_DFILE_FS: 'fs_dreal',
85
+ TX_TYPE_PFILE_VIRTUAL: 'fs_pvirt',
86
+ TX_TYPE_REQUEST: 'request',
87
+ TX_TYPE_REQUEST_IN: 'request_in',
88
+ TX_TYPE_REQUEST_UPLOAD: 'request_upload',
89
+ TX_TYPE_REQUEST_CANCEL: 'request_Cancel',
90
+ TX_TYPE_DATA_ROOM: 'data_room',
91
+ TX_TYPE_DATA_ROOMF: 'data_roomF',
92
+ TX_TYPE_DATA_ROOM_POLICY: 'data_room_policy',
93
+ TX_TYPE_DATA_ROOM_DATA: 'data_room_data',
94
+ TX_TYPE_DATA_ROOM_DATA_DELETE: 'data_room_data_delete',
95
+ TX_TYPE_DATA_ROOM_DATA_POLICY: 'data_room_data_policy',
96
+ TX_TYPE_DATA_ROOME: 'data_roomE',
97
+ TX_TYPE_DATA_ROOME_DATA: 'data_roomE_data',
98
+ TX_TYPE_MULTI_DATA_ROOM: 'multi_data_room',
99
+ TX_TYPE_MULTI_STORAGE: 'multi_storage',
100
+ TX_TYPE_MULTI_TRANSFER: 'multi_transfer',
101
+ TX_TYPE_MULTI_TRANSFER_SENT: 'multi_transfer_sent',
102
+ TX_TYPE_MULTI_BACKUP: 'multi_backup',
103
+ TX_TYPE_MULTI_PASSWD: 'multi_passwd',
104
+ TX_TYPE_MULTI_COLLECTION: 'multi_collection',
105
+ TX_TYPE_MULTI_DATAV2: 'multi_dataV2',
106
+ TX_TYPE_PASSWD_DATA: 'passwd_data',
107
+ TX_TYPE_PASSWD_ROOM: 'passwd_room',
108
+ TX_TYPE_PASSWD_ROOMF: 'passwd_roomF',
109
+ TX_TYPE_PASSWD_ROOM_POLICY: 'passwd_room_policy',
110
+ TX_TYPE_PASSWD_ROOM_DATA: 'passwd_room_data',
111
+ TX_TYPE_PASSWD_ROOM_DATA_DELETE: 'passwd_room_data_delete',
112
+ TX_TYPE_PASSWD_ROOM_DATA_POLICY: 'passwd_room_data_policy',
113
+ TX_TYPE_DATAV2: 'datav2',
114
+ TX_TYPE_DATAV2_POLICY: 'datav2_policy',
115
+ TX_TYPE_COLLECTION: 'coll',
116
+ TX_TYPE_COLLECTION_POLICY: 'coll_policy',
117
+ TX_TYPE_DATAV2_COLLECTION: 'datav2_coll',
118
+ TX_TYPE_DATAV2F: 'datav2F',
119
+ TX_TYPE_LIST: readonly TXType[]
120
+
121
+ export interface TransactionInput {
122
+ id: string
123
+ height: number
124
+ version: number
125
+ typ: TXType
126
+ sender_addr: string
127
+ recipient_addr: string
128
+ data: JSONValue
129
+ sign: string
130
+ fee: number
131
+ hash?: string
132
+ /** Date text/RFC3339Nano, Unix milliseconds or a caller-owned Date. */
133
+ inserted_at?: string | number | Date
134
+ additionalData?: JSONValue
135
+ cipherData?: JSONValue
136
+ chainName?: string
137
+ chainVersion?: string
138
+ }
139
+
140
+ /** Factory results and their JSON data are immutable snapshots. */
63
141
  export declare class Transaction {
64
- constructor({
65
- id,
66
- height,
67
- version,
68
- typ,
69
- sender_addr,
70
- recipient_addr,
71
- data,
72
- sign,
73
- fee,
74
- hash,
75
- inserted_at,
76
- additionalData,
77
- cipherData,
78
- chainName,
79
- chainVersion
80
- }?: Record<string, any>)
81
- get Order(): number
142
+ constructor(input?: Partial<TransactionInput>)
143
+
144
+ get Order(): number | undefined
145
+
82
146
  get ID(): string
147
+
83
148
  get Height(): number
149
+
84
150
  get Version(): number
151
+
85
152
  get Typ(): TXType
153
+
86
154
  get SenderAddr(): string
155
+
87
156
  get RecipientAddr(): string
88
- get Data(): string
89
- get AdditionalData(): string
90
- get CipherData(): string
157
+
158
+ get Data(): JSONValue
159
+
160
+ get AdditionalData(): JSONValue | undefined
161
+
162
+ get CipherData(): JSONValue | undefined
163
+
91
164
  get Sign(): string
165
+
92
166
  get Fee(): number
93
- get Hash(): string
94
- get InsertedAt(): Date
95
- get ChainName(): string
96
- get ChainVersion(): string
97
- static FromJSON(value: string): { transaction?: Transaction; error?: Error }
98
- static FromObject(obj: Record<string, any>): {
99
- transaction?: Transaction
100
- error?: Error
101
- }
167
+
168
+ get Hash(): string | undefined
169
+
170
+ /** Returns a detached Date; mutating it never changes the transaction. */
171
+ get InsertedAt(): Date | undefined
172
+
173
+ get ChainName(): string | undefined
174
+
175
+ get ChainVersion(): string | undefined
176
+
177
+ static FromJSON(
178
+ value: string
179
+ ): ParseResult<'transaction', Readonly<Transaction>>
180
+
181
+ static FromObject(
182
+ obj: Record<string, unknown>
183
+ ): ParseResult<'transaction', Readonly<Transaction>>
184
+
185
+ Validate(): void
186
+
102
187
  ToJSON(): string
103
- ToObject(): Record<string, any>
188
+
189
+ ToObject(): Readonly<Record<string, JSONValue>>
104
190
  }